【问题标题】:415 Unsupported media type on java rest service when uploading file415 上传文件时 java rest 服务上不支持的媒体类型
【发布时间】:2018-10-29 05:47:06
【问题描述】:

我正在尝试构建一个休息服务来上传文件。这就是我所拥有的。当我在邮递员中进行测试时,我选择了表单数据,并将“文件”设置为我正在上传的文件。

@POST
@Path("/upload")
@Consumes(MediaType.MULTIPART_FORM_DATA)
public Response upload(@RequestParam("file") MultipartFile file)

我的理解是我需要 jersey-media-multipart 依赖

<dependency>
    <groupId>org.glassfish.jersey.media</groupId>
    <artifactId>jersey-media-multipart</artifactId>
    <version>2.25.1</version>
</dependency>

当我尝试发出发布请求时,我收到 415 Unsupported Media Type 错误,我不知道为什么。设置为消耗MULTIPART_FORM_DATA,参数为MultipartFile。

EDIT我添加了如下配置,

@Configuration
public class JerseyConfig extends ResourceConfig {
    public JerseyConfig() {
        register(MultiPartFeature.class);
    }
}

我也修复了我的资源

@POST
@Path("/upload")
@Consumes(MediaType.MULTIPART_FORM_DATA)
public Response upload(
        @FormDataParam("file") InputStream file,
        @FormDataParam("file") FormDataContentDisposition fdcd,
        @FormDataParam("file-detail") String fileDetail) throws IOException {

现在我得到[[FATAL] No injection source found for a parameter of type public javax.ws.rs.core.Response

这是我的 Spring Boot 类,其中包含额外的配置

    @SpringBootApplication
@EnableCircuitBreaker
@EntityScan("com.whatever.")
@ImportResource({"classpath*:/META-INF/**/spring-bootstrap.xml"})
@Import({JerseyConfig.class})
@EnableJpaRepositories(basePackages="whatever", entityManagerFactoryRef="entityManagerFactory")
public class Application {

protected TomcatEmbeddedServletContainerFactory createTomcatEmbeddedServletContainerFactory() {
        return new TomcatEmbeddedServletContainerFactory() {

            @Override
            protected TomcatEmbeddedServletContainer getTomcatEmbeddedServletContainer(Tomcat tomcat) {
                ((StandardHost) tomcat.getHost()).setErrorReportValveClass(StringUtils.EMPTY);
                return super.getTomcatEmbeddedServletContainer(tomcat);
            }
        };
    }

    @Bean
    public FilterRegistrationBean requestContextFilter() {
        FilterRegistrationBean filterRegistration = new FilterRegistrationBean(new org.springframework.web.filter.RequestContextFilter());
        filterRegistration.setName("RequestContextFilter");
        filterRegistration.setOrder(Ordered.HIGHEST_PRECEDENCE + 1);
        filterRegistration.addUrlPatterns(BASE_PATH + "*");
        return filterRegistration;
    }    

    @Bean 
    public FilterRegistrationBean springSecurityFilterChain() {
        FilterRegistrationBean filterRegistration = new FilterRegistrationBean(new org.springframework.web.filter.DelegatingFilterProxy());
        filterRegistration.setName("SpringSecurityFilterChain");
        filterRegistration.setOrder(Ordered.HIGHEST_PRECEDENCE + 2);
        filterRegistration.addUrlPatterns(BASE_PATH + "*");
        return filterRegistration;
    }

    @Bean
    @Conditional(NonWindowsCondition.class)
    public FilterRegistrationBean f5Filter() {
        FilterRegistrationBean filterRegistration = new FilterRegistrationBean(new F5Filter());
        filterRegistration.setName("F5Filter");
        filterRegistration.setOrder(Ordered.HIGHEST_PRECEDENCE + 3);
        filterRegistration.addUrlPatterns(BASE_PATH + "*");
        return filterRegistration;
    }  

    /**
     * Initializes and registers the JAX-RS filter implementation, currently Jersey.
     * 
     * @return The JAX-RS filter registration.
     * @throws ClassNotFoundException 
     * @throws IllegalAccessException 
     * @throws InstantiationException 
     */
    @Bean
    public FilterRegistrationBean jaxrsFilter() throws InstantiationException, IllegalAccessException, ClassNotFoundException {
        Filter filter = (Filter) Class.forName("org.glassfish.jersey.servlet.ServletContainer").newInstance();
        jerseyFilterRegistration.setFilter(filter);
        jerseyFilterRegistration.setName("JerseyFilter");
        jerseyFilterRegistration.setDispatcherTypes(EnumSet.allOf(DispatcherType.class));
        // Set the Jersey filter mapping and context path
        jerseyFilterRegistration.addUrlPatterns(BASE_PATH + "*");
        jerseyFilterRegistration.addInitParameter("jersey.config.servlet.filter.contextPath", BASE_PATH);
        // Load the common package and application package
        jerseyFilterRegistration.addInitParameter("jersey.config.server.provider.packages", "com.whatever.jaxrs.feature;com.whatever.fig.risk.webservice.resource");
        // Enable media type mappings on the URI such as .xml and .json
        jerseyFilterRegistration.addInitParameter("jersey.config.server.mediaTypeMappings", "xml:application/xml, json:application/json");
        // Enable Java bean validation integration
        jerseyFilterRegistration.addInitParameter("jersey.config.beanValidation.enableOutputValidationErrorEntity.servers", "true");
        // Disable the application.wadl from being generated and publicly visible (ITSO finding)
        jerseyFilterRegistration.addInitParameter("jersey.config.server.wadl.disableWadl", "true");        
        // Forward 404s to Spring MVC, which serves up the Actuator endpoints and non-jersey resources 
        jerseyFilterRegistration.addInitParameter("jersey.config.servlet.filter.forwardOn404", "true");

        if (isJerseyDebug) {
            // Debug parameter switches
            jerseyFilterRegistration.addInitParameter("jersey.config.server.monitoring.statistics.enabled", "true");
            jerseyFilterRegistration.addInitParameter("jersey.config.server.tracing.type", "ALL");
            jerseyFilterRegistration.addInitParameter("jersey.config.server.tracing.threshold", "VERBOSE");
        }

        return jerseyFilterRegistration;
    }

【问题讨论】:

  • 您的JerseyConfig 不是正在使用的配置类。如果是,您将不会收到此错误。你是如何配置你的应用程序的?是 web.xml 吗?你用的是 Spring Boot 吗?
  • 我正在使用 Spring Boot。所以我猜我的主类需要扩展 ResourceConfig
  • JerseyConfig 类,您正在配置 Jersey 应用程序的其余部分吗?
  • 我已经从我的主要 Spring Boot 类中复制了一些配置内容。这就是我所拥有的。我不认为它适用于我们目前的情况,但我可能错了。我在球衣配置中只有你建议我添加的那一行。
  • 不知道为什么要这样配置 Jersey,即使用 FilterRegistrationBean。如果您打算这样做,那么您需要从我的答案中的链接中查看 MultiPartFeature 的 init-param 配置。

标签: rest jersey jax-rs


【解决方案1】:

@RequestParamMultipartFile 都是 Spring 而不是 Jersey。对于 Jersey,您要使用注释 @FormDataParam 和参数,根据零件类型,您可以有许多不同类型的参数。如果部件是文件,您可以使用InputStreamFilebyte[] 参数,或者如果部件是纯文本,则可以使用字符串参数。如果您想要文件名,您可以在部件实体参数旁边添加一个FormDataContentDisposition 参数。下面是一个例子

@POST
@Consumes(MediaType.MULTIPART_FORM_DATA)
public Response upload(
        @FormDataParam("file") InputStream file,
        @FormDataParam("file") FormDataContentDisposition fdcd,
        @FormDataParam("file-detail") String fileDetail) {

}

要完成这项工作,您需要在您的应用程序中注册MultiPartFeature。您可以查看this post 了解注册方式。


另请参阅:

【讨论】:

    猜你喜欢
    • 2021-05-26
    • 2014-09-15
    • 2021-10-15
    • 1970-01-01
    • 1970-01-01
    • 2021-05-20
    • 2014-05-25
    • 2019-10-07
    • 2015-07-21
    相关资源
    最近更新 更多