Search code examples
springspring-mvcapache-commons-fileupload

CommonsMultipartResolver and HandlerExceptionResolver working inconsistently


I am trying to create a simple form for uploading files using Spring and CommonsMultipartResolver.

I am using Spring 4.0.6.RELEASE with Tomcat v7.0.57. I have added these Apache dependencies to my pom file:

        <!-- Apache Commons FileUpload -->
    <dependency>
        <groupId>commons-fileupload</groupId>
        <artifactId>commons-fileupload</artifactId>
        <version>1.3.1</version>
    </dependency>

    <!-- Apache Commons IO -->
    <dependency>
        <groupId>commons-io</groupId>
        <artifactId>commons-io</artifactId>
        <version>2.4</version>
    </dependency>

I have the following configuration in my spring xml file:

<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
    <property name="maxUploadSize" value="5120000" />
</bean>

And I have added the following method to my controller:

@Override
public ModelAndView resolveException(HttpServletRequest request, HttpServletResponse httpServletResponse, Object o, Exception e) {
    ModelAndView modelAndView = new ModelAndView();
    modelAndView.setViewName("website/upload");
    if (e instanceof MaxUploadSizeExceededException)
    {
        modelAndView.addObject("errors", "Maximum upload size of " + (((MaxUploadSizeExceededException) e).getMaxUploadSize() + " bytes exceeded"));
    }
    else
    {
        modelAndView.addObject("errors", "An unexpected error occurred.  Please try again later.");
    }

    return modelAndView;
}

If I set the maxUploadSize to something smaller (i.e. 1mb) and upload a file a bit larger (I tested with a file that was 1.7mb), this works correctly and the page is displayed showing the user the error. However, with the larger limit of 5MB, if I upload a file that is just a few bytes larger than the limit, my resolveException method is invoked multiple times, but the page is not loaded. I tested using both Chrome and Firefox. In Firefox I get an error saying that "The connection was reset". In the network tab, it says that the POST was "Aborted". In Chrome, I get an error saying "This webpage is not available" with Error Code: ERR_CONNECTION_RESET. In the network tab the POST simply says that it "failed".

My guess is that with larger file uploads, it is canceling the file upload before it completes, which is behavior I would like to keep. However, I would still like to show the user a nicer error in these cases.

I tried increasing the maxInMemorySize attribute of CommonsMultipartResolver to 10mb, but this did not seem to have any effect. Could someone help me figure out where I'm going wrong?


Solution

  • Finally figured out the problem. It actually has nothing to do with HandlerExceptionResolver and seems to be due to a setting in the version of Tomcat that I am using (7.0.57). In the server.xml, I had to specify the "maxSwallowSize" property on my Connector.

    According to the Tomcat documentation, maxSwallowSize is "The maximum number of request body bytes (excluding transfer encoding overhead) that will be swallowed by Tomcat for an aborted upload. An aborted upload is when Tomcat knows that the request body is going to be ignored but the client still sends it. If Tomcat does not swallow the body the client is unlikely to see the response. If not specified the default of 2097152 (2 megabytes) will be used. A value of less than zero indicates that no limit should be enforced."

    http://tomcat.apache.org/tomcat-7.0-doc/config/http.html