4

I'm running Jetty 9 (jetty-9.0.5.v20130815) server with servlet-api 3.0.1 (javax.servlet:javax.servlet-api:3.0.1), my servlet is configured to accept multipart requests.

web.xml -

<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
     xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee"
     xmlns:c="http://java.sun.com/jsp/jstl/core"
     xmlns:fmt="http://java.sun.com/jsp/jstl/fmt"
     xmlns:web="http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
     version="3.1" xmlns="http://xmlns.jcp.org/xml/ns/javaee">

<servlet>
    <servlet-name>restapi</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet
    </servlet-class>
    <load-on-startup>1</load-on-startup>
    <multipart-form enable="true" />
    <multipart-config>
        <max-file-size>8428800</max-file-size>
        <max-request-size>8428800</max-request-size>
        <file-size-threshold>1048576</file-size-threshold>
    </multipart-config>
</servlet>
</web-app>

applicationContext.xml -

<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
    <!-- one of the properties available; the maximum file size in bytes -->
    <property name="maxUploadSize" value="8000000"/>
</bean>

It implements a POST command that should receive a file upload through HttpServletRequest. But when request.getParts() is called, this exception occurs:

java.io.IOException: Missing content for multipart request
        at org.eclipse.jetty.util.MultiPartInputStreamParser.parse(MultiPartInputStreamParser.java:493)
        at org.eclipse.jetty.util.MultiPartInputStreamParser.getParts(MultiPartInputStreamParser.java:401)
        at org.eclipse.jetty.server.Request.getParts(Request.java:2077)
        at javax.servlet.http.HttpServletRequestWrapper.getParts(HttpServletRequestWrapper.java:351)
        at javax.servlet.http.HttpServletRequestWrapper.getParts(HttpServletRequestWrapper.java:351)

The client is an iOS app using ASIFormDataRequest, but I don't think that client has the problem because it used to work with Apache commons-fileupload.jar. I'm not switching the server to use Jetty's multipart support for receiving files.

Here's the request, as intercepted by a proxy -

POST /mycommand HTTP/1.1
Host: localhost:8080
Proxy-Connection: close
Accept-Encoding: gzip
Content-Type: multipart/form-data; charset=utf-8; boundary=0xKhTmLbOuNdArY-849F4DA3-85DC-46F1-B182-44257808F0B9
Content-Length: 1568
Connection: close

--0xKhTmLbOuNdArY-849F4DA3-85DC-46F1-B182-44257808F0B9
Content-Disposition: form-data; name="param1"

text
--0xKhTmLbOuNdArY-849F4DA3-85DC-46F1-B182-44257808F0B9
Content-Disposition: form-data; name="data"; filename="file"
Content-Type: application/octet-stream

... DATA ...
--0xKhTmLbOuNdArY-849F4DA3-85DC-46F1-B182-44257808F0B9--

Any ideas?

Kof
  • 23,893
  • 9
  • 56
  • 81
  • are you abbreviating for the request example? "text" and "... DATA ..." ? – Joakim Erdfelt Dec 16 '13 at 15:33
  • Yea, `text` was my email and `DATA` was a long binary data (not readable). – Kof Dec 16 '13 at 15:57
  • You will need to capture that multipart request in a way that shows the carriage return/line feed chars as these are important in delineating the boundaries and content. Assuming that the CR/LF chars are in the correct positions, then the above example works when used with jetty 9.1, and I don't think there were any multipart bugs fixed after 9.0.5. – Jan Dec 18 '13 at 22:41
  • @Kof Did you figure this one out? I'm having the same problem now with Jetty 9.2.3 – Aleksander Blomskøld Sep 17 '14 at 05:51
  • No, had to work around it. – Kof Sep 17 '14 at 12:38
  • It reproduced today with a new version of Java and Jetty, the solution below helped. – Kof Jul 06 '15 at 17:30

4 Answers4

4

We had the exact same problem, and after some hours of debugging we found the issue.

Jetty complains because the InputStream that contains the mulitpart message is empty. The issue for us was that both both Servlet 3.0-style multipart was configured (as you have done with the multipart-* tags in web.xml), and Spring was configured to use Commons FileUpload for multipart parsing. This caused Commons FileUpload to consume the InputStream before Jetty did it in the MultiPartInputStreamParser

The solution to this is simply to remove Commons FileUpload from the classpath and configure Spring not to use it.

Aleksander Blomskøld
  • 18,374
  • 9
  • 76
  • 82
  • Very interesting, but this problem doesn't reproduce now so I can't test it. – Kof Sep 22 '14 at 17:09
  • 1
    Good catch, I removed `multipart-*` from web.xml and it now works with `commons-fileupload`. – Kof Jul 06 '15 at 17:29
0

The error for "Missing content for multipart request" is due to a missing or badly detected first boundary.

There have been numerous edge cases (from clients that badly format multi-part messages) that Jetty compensates for. However, the information you have provided is insufficient to know what the underlying cause might be.

Can you file a bug at bugs.eclipse.org under RT/Jetty with a wireshark capture of the traffic?

Joakim Erdfelt
  • 46,896
  • 7
  • 86
  • 136
0

for spring boot application I found same issue. I remove Commons FileUpload lib and add to properties:

multipart:
  maxFileSize: 32Mb
  maxRequestSize: 32Mb

for size files

z0mb1ek
  • 899
  • 9
  • 16
0

In my case i had the following ; when i commented the lines below in

org.springframework.web.servlet.DispatcherServlet

It worked.....after commenting

 <servlet>
        <servlet-name>default</servlet-name>
        <servlet-class>org.apache.catalina.servlets.DefaultServlet</servlet-class>
        <init-param>
            <param-name>debug</param-name>
            <param-value>0</param-value>
        </init-param>
        <init-param>
            <param-name>listings</param-name>
            <param-value>false</param-value>
        </init-param>
        <load-on-startup>1</load-on-startup>
        <multipart-config>
            <!-- 52MB max -->
            <max-file-size>52428800</max-file-size>
            <max-request-size>52428800</max-request-size>
            <file-size-threshold>0</file-size-threshold>
        </multipart-config>
    </servlet>
    <servlet-mapping>
        <servlet-name>default</servlet-name>
        <url-pattern>*.ico</url-pattern>
        <url-pattern>*.png</url-pattern>
        <url-pattern>*.jpg</url-pattern>
        <url-pattern>*.htc</url-pattern>
        <url-pattern>*.gif</url-pattern>
        <url-pattern>*.swf</url-pattern>
        <url-pattern>*.wmf</url-pattern>
        <url-pattern>*.pdf</url-pattern>
        <url-pattern>*.css</url-pattern>
        <url-pattern>*.js</url-pattern>
        <url-pattern>*.json</url-pattern>
        <url-pattern>*.otf</url-pattern>
        <url-pattern>*.eot</url-pattern>
        <url-pattern>*.svg</url-pattern>
        <url-pattern>*.ttf</url-pattern>
        <url-pattern>*.woff</url-pattern>
        <url-pattern>/files/original/*</url-pattern>      
    </servlet-mapping>
    <servlet>
        <servlet-name>dispatcher</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <load-on-startup>2</load-on-startup>
<!--        <multipart-config>
             52MB max 
            <max-file-size>52428800</max-file-size>
            <max-request-size>52428800</max-request-size>
            <file-size-threshold>0</file-size-threshold>
        </multipart-config>-->
    </servlet>
    <servlet-mapping>
        <servlet-name>dispatcher</servlet-name>
        <url-pattern>*.html</url-pattern>
        <url-pattern>*.txt</url-pattern>
        <url-pattern>*.xml</url-pattern>
        <url-pattern>/</url-pattern>
    </servlet-mapping>
shareef
  • 9,255
  • 13
  • 58
  • 89