Hi,
I have an server application with Netty 4.0.9 and Jersey 2.15. Everything
works fine except the 'multipart/form-data' with the WebKit browser (Chrome
and Safari).
When I use Chrome or Safari I receive this error:
* javax.ws.rs.BadRequestException: HTTP 400 Bad Request*
* at
org.glassfish.jersey.media.multipart.internal.MultiPartReaderClientSide.readFrom(MultiPartReaderClientSide.java:184)*
* at
org.glassfish.jersey.media.multipart.internal.MultiPartReaderClientSide.readFrom(MultiPartReaderClientSide.java:91)*
* at
org.glassfish.jersey.message.internal.ReaderInterceptorExecutor$TerminalReaderInterceptor.invokeReadFrom(ReaderInterceptorExecutor.java:258)*
* at
org.glassfish.jersey.message.internal.ReaderInterceptorExecutor$TerminalReaderInterceptor.aroundReadFrom(ReaderInterceptorExecutor.java:234)*
* at
org.glassfish.jersey.message.internal.ReaderInterceptorExecutor.proceed(ReaderInterceptorExecutor.java:154)*
* at
org.glassfish.jersey.server.internal.MappableExceptionWrapperInterceptor.aroundReadFrom(MappableExceptionWrapperInterceptor.java:73)*
* at
org.glassfish.jersey.message.internal.ReaderInterceptorExecutor.proceed(ReaderInterceptorExecutor.java:154)*
* at
org.glassfish.jersey.message.internal.MessageBodyFactory.readFrom(MessageBodyFactory.java:1124)*
* at
org.glassfish.jersey.message.internal.InboundMessageContext.readEntity(InboundMessageContext.java:851)*
* at
org.glassfish.jersey.message.internal.InboundMessageContext.readEntity(InboundMessageContext.java:783)*
* at
org.glassfish.jersey.server.ContainerRequest.readEntity(ContainerRequest.java:233)*
* at
org.glassfish.jersey.media.multipart.internal.FormDataParamValueFactoryProvider.getEntity(FormDataParamValueFactoryProvider.java:376)*
* at
org.glassfish.jersey.media.multipart.internal.FormDataParamValueFactoryProvider.access$000(FormDataParamValueFactoryProvider.java:87)*
* at
org.glassfish.jersey.media.multipart.internal.FormDataParamValueFactoryProvider$FormDataParamValueFactory.provide(FormDataParamValueFactoryProvider.java:203)*
* at
org.glassfish.jersey.server.spi.internal.ParameterValueHelper.getParameterValues(ParameterValueHelper.java:81)*
* at
org.glassfish.jersey.server.model.internal.JavaResourceMethodDispatcherProvider$AbstractMethodParamInvoker.getParamValues(JavaResourceMethodDispatcherProvider.java:121)*
* at
org.glassfish.jersey.server.model.internal.JavaResourceMethodDispatcherProvider$VoidOutInvoker.doDispatch(JavaResourceMethodDispatcherProvider.java:136)*
* at
org.glassfish.jersey.server.model.internal.AbstractJavaResourceMethodDispatcher.dispatch(AbstractJavaResourceMethodDispatcher.java:104)*
* at
org.glassfish.jersey.server.model.ResourceMethodInvoker.invoke(ResourceMethodInvoker.java:384)*
* at
org.glassfish.jersey.server.model.ResourceMethodInvoker.apply(ResourceMethodInvoker.java:342)*
* at
org.glassfish.jersey.server.model.ResourceMethodInvoker.apply(ResourceMethodInvoker.java:101)*
* at
org.glassfish.jersey.server.JerseyApplicationHandlerRuntime$1.run(JerseyApplicationHandlerRuntime.java:229)*
* at org.glassfish.jersey.internal.Errors$1.call(Errors.java:271)*
* at org.glassfish.jersey.internal.Errors$1.call(Errors.java:267)*
* at org.glassfish.jersey.internal.Errors.process(Errors.java:315)*
* at org.glassfish.jersey.internal.Errors.process(Errors.java:297)*
* at org.glassfish.jersey.internal.Errors.process(Errors.java:267)*
* at
org.glassfish.jersey.process.internal.RequestScope.runInScope(RequestScope.java:316)*
* at
org.glassfish.jersey.server.JerseyApplicationHandlerRuntime.process(JerseyApplicationHandlerRuntime.java:208)*
* at
org.glassfish.jersey.server.JerseyApplicationHandler.handle(JerseyApplicationHandler.java:1019)*
* ...*
*Caused by: org.jvnet.mimepull.MIMEParsingException: Missing start boundary*
* at org.jvnet.mimepull.MIMEParser.skipPreamble(MIMEParser.java:313)*
* at org.jvnet.mimepull.MIMEParser.access$300(MIMEParser.java:68)*
* at
org.jvnet.mimepull.MIMEParser$MIMEEventIterator.next(MIMEParser.java:149)*
* at
org.jvnet.mimepull.MIMEParser$MIMEEventIterator.next(MIMEParser.java:132)*
* at org.jvnet.mimepull.MIMEMessage.makeProgress(MIMEMessage.java:198)*
* at org.jvnet.mimepull.MIMEMessage.parseAll(MIMEMessage.java:181)*
* at org.jvnet.mimepull.MIMEMessage.getAttachments(MIMEMessage.java:106)*
* at
org.glassfish.jersey.media.multipart.internal.MultiPartReaderClientSide.readMultiPart(MultiPartReaderClientSide.java:225)*
* at
org.glassfish.jersey.media.multipart.internal.MultiPartReaderServerSide.readMultiPart(MultiPartReaderServerSide.java:90)*
* at
org.glassfish.jersey.media.multipart.internal.MultiPartReaderClientSide.readFrom(MultiPartReaderClientSide.java:179)*
* ... 36 common frames omitted*
With Firefox or IE I don't have problem.
If i intercept the data of the HTTP request between Netty and Jersey, I got
this result :
*With Firefox (Working)*
*//startContent*
*-----------------------------2382551017519*
*Content-Disposition: form-data; name="file"; filename="foo.txt"*
*Content-Type: text/plain*
*bar*
*-----------------------------2382551017519--*
*//endContent*
*//byte*
*45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 50, 51, 56, 50, 53, 53, 49, 48,
49, 55, 53, 49, 57, 13, 10, 67, 111, 110, 116, 101, 110, 116, 45, 68, 105,
115, 112, 111, 115, 105, 116, 105, 111, 110, 58, 32, 102, 111, 114, 109,
45, 100, 97, 116, 97, 59, 32, 110, 97, 109, 101, 61, 34, 102, 105, 108,
101, 34, 59, 32, 102, 105, 108, 101, 110, 97, 109, 101, 61, 34, 102, 111,
111, 46, 116, 120, 116, 34, 13, 10, 67, 111, 110, 116, 101, 110, 116, 45,
84, 121, 112, 101, 58, 32, 116, 101, 120, 116, 47, 112, 108, 97, 105, 110,
13, 10, 13, 10, 98, 97, 114, 13, 10, 45, 45, 45, 45, 45, 45, 45, 45, 45,
45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
45, 50, 51, 56, 50, 53, 53, 49, 48, 49, 55, 53, 49, 57, 45, 45, 13, 10*
*//header*
*Host : localhost*
*User-Agent : Mozilla/5.0 (Windows NT 6.1; WOW64; rv:34.0) Gecko/20100101
Firefox/34.0*
*Accept : */**
*Accept-Language : fr,fr-fr;q=0.8,en-us;q=0.5,en;q=0.3*
*Accept-Encoding : gzip, deflate*
*Referer :
http://10.0.16.56:8080/ <
http://10.0.16.56:8080/>*
*Origin :
http://10.0.16.56:8080 <
http://10.0.16.56:8080>*
*Connection : keep-alive*
*Pragma : no-cache*
*Cache-Control : no-cache*
*Content-Length : 188*
*Content-Type : multipart/form-data;
boundary=---------------------------2382551017519*
*With Chrome (Not Working)*
*//[startContent]*
*------WebKitFormBoundaryg7okV37G7Gfll2hf*
*Content-Disposition: form-data; name="file"; filename="foo.txt"*
*Content-Type: text/plain*
*bar*
*------WebKitFormBoundaryg7okV37G7Gfll2hf--*
*//[endContent]*
*//byte*
*45, 45, 45, 45, 45, 45, 87, 101, 98, 75, 105, 116, 70, 111, 114, 109, 66,
111, 117, 110, 100, 97, 114, 121, 103, 55, 111, 107, 86, 51, 55, 71, 55,
71, 102, 108, 108, 50, 104, 102, 13, 10, 67, 111, 110, 116, 101, 110, 116,
45, 68, 105, 115, 112, 111, 115, 105, 116, 105, 111, 110, 58, 32, 102, 111,
114, 109, 45, 100, 97, 116, 97, 59, 32, 110, 97, 109, 101, 61, 34, 102,
105, 108, 101, 34, 59, 32, 102, 105, 108, 101, 110, 97, 109, 101, 61, 34,
102, 111, 111, 46, 116, 120, 116, 34, 13, 10, 67, 111, 110, 116, 101, 110,
116, 45, 84, 121, 112, 101, 58, 32, 116, 101, 120, 116, 47, 112, 108, 97,
105, 110, 13, 10, 13, 10, 98, 97, 114, 13, 10, 45, 45, 45, 45, 45, 45, 87,
101, 98, 75, 105, 116, 70, 111, 114, 109, 66, 111, 117, 110, 100, 97, 114,
121, 103, 55, 111, 107, 86, 51, 55, 71, 55, 71, 102, 108, 108, 50, 104,
102, 45, 45, 13, 10*
*//header*
*Host : localhost*
*User-Agent : Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36
(KHTML, like Gecko) Chrome/39.0.2171.99 Safari/537.36*
*Accept : */**
*Accept-Language : fr-FR,fr;q=0.8,en-US;q=0.6,en;q=0.4*
*Accept-Encoding : gzip, deflate*
*Referer :
http://10.0.16.56:8080/ <
http://10.0.16.56:8080/>*
*Origin :
http://10.0.16.56:8080 <
http://10.0.16.56:8080>*
*Connection : keep-alive*
*Content-Length : 184*
*Content-Type : multipart/form-data;
boundary=----webkitformboundaryg7okv37g7gfll2hf*
*For my test I used a pure HTTP request*
* <form id="data" enctype="multipart/form-data" method="post"
action="
http://localhost/api/file/upload
<
http://localhost/api/file/upload>">>*
* <!-- <form id="data" enctype="multipart/form-data" method="post"
action="
http://localhost:9000/file/upload
<
http://localhost:9000/file/upload>">>-->*
* Profile Image: <input name="file" type="file" /><br />*
* <input type="submit" value="Submit">*
* </form>*
*My Jersey Resource look like this*
* @Path("/file")*
* @Produces(MediaType.APPLICATION_JSON)*
* public class FileResource*
* {*
* @POST*
* @Path("/upload")*
* @Consumes(MediaType.MULTIPART_FORM_DATA)*
* public void uploadFile(@FormDataParam("file") InputStream stream,
@FormDataParam("file") FormDataContentDisposition contentDispositionHeader)*
* {*
* String outputPath = "C:/upload/";*
* java.nio.file.Path outPath = FileSystems.getDefault().getPath(outputPath,
contentDispositionHeader.getFileName());*
* try*
* {*
* Files.copy(stream, outPath);*
* }*
* catch (IOException e)*
* {*
* throw Throwables.propagate(e);*
* }*
* }*
* }*
*My Gradle dependencies*
*compile group: "org.glassfish.jersey.core", name: "jersey-server",
version: "2.15"*
* compile group: "org.glassfish.jersey.media", name:
"jersey-media-json-jackson", version: "2.15"*
* compile group: "org.glassfish.jersey.media", name:
"jersey-media-multipart", version: "2.15"*
*My Jersey Application*
* public class JerseyApplication extends ResourceConfig*
* {*
* public JerseyApplication()*
* {*
* super(JacksonMapper.class, JacksonFeature.class);*
* register(new InjectionBinder());*
* register(new MultiPartFeature());*
* ...*
* }*
* }*
Thx for the help
Pascal Lemay