Web 应用程序异常:javax.ws.rs.NotSupportedException:HTTP 415 不支持的媒体类型

Web Application Exception: javax.ws.rs.NotSupportedException: HTTP 415 Unsupported Media Type

我在我的应用程序中使用球衣和 spring。我在处理任何 AJAX 请求时没有任何问题,但在上传文件时出现媒体不支持错误。我尝试了几种方法,但还没有找到任何修复方法。想知道是否有人可以帮助我找到问题的根本原因。感谢你的帮助。

服务器端实现

web.xml

<servlet>
    <servlet-name>jersey-servlet</servlet-name>
    <servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
    <init-param>
        <param-name>javax.ws.rs.Application</param-name>
        <param-value>org.blanc.whiteboard.RestResourceApplication</param-value>
    </init-param>
    <init-param>
        <param-name>org.glassfish.jersey.api.json.POJOMappingFeature</param-name>
        <param-value>true</param-value>
    </init-param>
    <init-param>
        <param-name>jersey.config.server.provider.classnames</param-name>
        <param-value>org.glassfish.jersey.filter.LoggingFilter;org.glassfish.jersey.media.multipart.MultiPartFeature</param-value>
    </init-param>
    <load-on-startup>1</load-on-startup>
</servlet>

资源class

@Path("/upload")
@POST
//@Consumes({ MediaType.MULTIPART_FORM_DATA })
public Response uploadAsset(@Context SecurityContext sc,
        MultipartHttpServletRequest request) {
    User user = loadUserFromSecurityContext(sc);
    MultipartFile file = null;
    // 1. build an iterator
    Iterator<String> itr = request.getFileNames();
    // 2. get each file
    while (itr.hasNext()) {
        // 2.1 get next MultipartFile
        file = request.getFile(itr.next());
        if (file == null) {
            throw new FileUploadException("File is null.");
        }
        LOG.info(file.getOriginalFilename() + " uploaded! " + files.size());
        // 2.2 if files > 10 remove the first from list
        if (files.size() > 10)
            files.pop();

    }
    return Response.ok().build();
}

pom.xml

    <jersey.version>2.20</jersey.version>
   .....
        <dependency>
        <groupId>org.glassfish.jersey.ext</groupId>
        <artifactId>jersey-spring3</artifactId>
        <version>${jersey.version}</version>
        <exclusions>
            <exclusion>
                <artifactId>spring-core</artifactId>
                <groupId>org.springframework</groupId>
            </exclusion>
            <exclusion>
                <artifactId>spring-aop</artifactId>
                <groupId>org.springframework</groupId>
            </exclusion>
            <exclusion>
                <artifactId>spring-beans</artifactId>
                <groupId>org.springframework</groupId>
            </exclusion>
            <exclusion>
                <artifactId>spring-context</artifactId>
                <groupId>org.springframework</groupId>
            </exclusion>
            <exclusion>
                <artifactId>spring-web</artifactId>
                <groupId>org.springframework</groupId>
            </exclusion>
        </exclusions>
    </dependency>
    <dependency>
        <groupId>org.glassfish.jersey.core</groupId>
        <artifactId>jersey-client</artifactId>
        <version>${jersey.version}</version>
    </dependency>
    <dependency>
        <groupId>org.glassfish.jersey.core</groupId>
        <artifactId>jersey-common</artifactId>
        <version>${jersey.version}</version>
    </dependency>
    <dependency>
        <groupId>org.glassfish.jersey.media</groupId>
        <artifactId>jersey-media-json-jackson</artifactId>
        <version>${jersey.version}</version>
    </dependency>
    <!-- File upload -->
    <dependency>
        <groupId>commons-fileupload</groupId>
        <artifactId>commons-fileupload</artifactId>
        <version>${commons-fileupload.version}</version>
    </dependency>
    <dependency>
        <groupId>commons-io</groupId>
        <artifactId>commons-io</artifactId>
        <version>${commons-io.version}</version>
    </dependency>

错误:

Aug 12, 2015 7:21:58 PM org.glassfish.jersey.filter.LoggingFilter log
INFO: 4 * Server responded with a response on thread http-bio-8080-exec-5
4 < 200
4 < Access-Control-Allow-Headers: X-HTTP-Method-Override, Content-Type, x-requested-with, Authorization, Cache-Control
4 < Access-Control-Allow-Methods: GET, POST, PUT, DELETE, OPTIONS
4 < Access-Control-Allow-Origin: http://localhost:9000
4 < Access-Control-Max-Age: 3600
4 < Content-Type: application/json

Aug 12, 2015 7:22:15 PM org.glassfish.jersey.filter.LoggingFilter log
INFO: 5 * Server has received a request on thread http-bio-8080-exec-1
5 > OPTIONS http://localhost:8080/v1.0/assets/upload
5 > accept: */*
5 > accept-encoding: gzip, deflate, sdch
5 > accept-language: en-US,en;q=0.8
5 > access-control-request-headers: accept, cache-control, content-type, x-requested-with
5 > access-control-request-method: POST
5 > cache-control: no-cache
5 > connection: keep-alive
5 > host: localhost:8080
5 > origin: http://localhost:9000
5 > pragma: no-cache
5 > referer: http://localhost:9000/debug.html
5 > user-agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/44.0.2403.130 Safari/537.36

Aug 12, 2015 7:22:15 PM org.glassfish.jersey.filter.LoggingFilter log
INFO: 5 * Server responded with a response on thread http-bio-8080-exec-1
5 < 200
5 < Access-Control-Allow-Headers: X-HTTP-Method-Override, Content-Type, x-requested-with, Authorization, Cache-Control
5 < Access-Control-Allow-Methods: GET, POST, PUT, DELETE, OPTIONS
5 < Access-Control-Allow-Origin: http://localhost:9000
5 < Access-Control-Max-Age: 3600
5 < Allow: POST,OPTIONS
5 < Content-Type: application/vnd.sun.wadl+xml
5 < Last-modified: Wed, 12 Aug 2015 19:22:15 EDT

Aug 12, 2015 7:22:15 PM org.glassfish.jersey.filter.LoggingFilter log
INFO: 6 * Server has received a request on thread http-bio-8080-exec-10
6 > POST http://localhost:8080/v1.0/assets/upload
6 > accept: application/json
6 > accept-encoding: gzip, deflate
6 > accept-language: en-US,en;q=0.8
6 > cache-control: no-cache
6 > connection: keep-alive
6 > content-length: 108054
6 > content-type: multipart/form-data; boundary=----WebKitFormBoundarywS3v9iwIqD3NwnYt
6 > host: localhost:8080
6 > origin: http://localhost:9000
6 > pragma: no-cache
6 > referer: http://localhost:9000/debug.html
6 > user-agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/44.0.2403.130 Safari/537.36
6 > x-requested-with: XMLHttpRequest

19:22:15.340 [http-bio-8080-exec-10] INFO  o.b.w.r.GenericExceptionMapper - Web Application Exception: **javax.ws.rs.NotSupportedException: HTTP 415 Unsupported Media Type**
Aug 12, 2015 7:22:15 PM org.glassfish.jersey.filter.LoggingFilter log
INFO: 6 * Server responded with a response on thread http-bio-8080-exec-10
6 < 415
6 < Access-Control-Allow-Headers: X-HTTP-Method-Override, Content-Type, x-requested-with, Authorization, Cache-Control
6 < Access-Control-Allow-Methods: GET, POST, PUT, DELETE, OPTIONS
6 < Access-Control-Allow-Origin: http://localhost:9000
6 < Access-Control-Max-Age: 3600

在前端我使用 [dropzone][1]

您不能只期望将请求主体解析为任意数据类型(即 MultipartHttpServletRequest)。它是如何工作的(使用 Jersey 和 JAX-RS)是通过 MessageBodyReaders(你可以阅读更多 here)。

基本上,基于请求的Content-Type(即multipart/form-data)和方法参数类型(MultipartHttpServletRequest),Jersey 将通过它的注册表查找MessageBodyReader 可以处理这两个因素。如果找不到,它将抛出您所面临的异常并发送 415。

也就是说,您应该 做的只是使用 multipart support already provided by Jersey。它带有所需的 MessageBodyReader 来处理多部分数据的一些 Jersey 特定(和其他常见)数据类型。你首先需要依赖

<dependency>
    <groupId>org.glassfish.jersey.media</groupId>
    <artifactId>jersey-media-multipart</artifactId>
    <version>${jersey2.version}</version>
</dependency>

然后您需要注册该功能,您已经通过在 init-param 中添加功能类名来完成此操作

<init-param>
    <param-name>jersey.config.server.provider.classnames</param-name>
    <param-value>
        org.glassfish.jersey.filter.LoggingFilter;
        org.glassfish.jersey.media.multipart.MultiPartFeature
    </param-value>
</init-param>

然后你只需要使用它的组件。我提供的 link 给出了完整的解释。使用此功能的最常见方法是对方法参数使用 @FormDataParam 注释。例如

@Consumes({ MediaType.MULTIPART_FORM_DATA })
public Response uploadAsset(@FormDataParam("file") InputStream in) {}

其中 InputStream 是 Content-Disposition 中名称为 "file" 的特定文件。

还有一些其他方法可以接受文件。您可以包含整个多部分正文,然后像您当前所做的那样遍历各个部分。例如

@Consumes({ MediaType.MULTIPART_FORM_DATA })
public Response uploadAsset(FormDataMultiPart multipart) {
    Map<String, List<FormDataBodyPart>> map = multipart.getFields();
    for (Map.Entry<String, List<FormDataBodyPart>> entry: map.entrySet()) {
        for (FormDataBodyPart part: entry.getValue()) {
            InputStream in = part.getEntityAs(InputStream.class);
            String name = part.getName();
        }
    }
}

有关更多信息,请访问我上面提供的link。