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)是通过 MessageBodyReader
s(你可以阅读更多 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。
我在我的应用程序中使用球衣和 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)是通过 MessageBodyReader
s(你可以阅读更多 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。