2

I've read the article "File upload using Spring MVC and annotation configuration" (http://www.raistudies.com/spring/spring-mvc/file-upload-spring-mvc-annotation)

I really learned some useful things from it and thanks for this article!

It works fine in Tomcat-8.0.20 when I upload a small file.

But , when I upload a large file which is larger than 3M bytes, the MaxUploadSizeExceededException would have been catched "twice" , then the connection between browser and server would be broken. The browser reports an ERR_CONNECTION_RESET error and no error info(or page) is shown, it just looks like the cable to my computer is pulled out by someone.

My system environment is : JRE1.8+Tomcat-8.0.20+WAR_package and my tomcat is a brand new clean tomcat in a new folder , which only has this WAR in it.

I tried by using Spring 4.1.4 , the problem still remains.

By the way ,the lazy mode of file-uploading is not suitable in my case. So I need to report result to user immediately when MaxUploadSizeExceededException has been catched. And this is what I expected.

How to resolve this "disconnection" problem caused by uploading large file ?

Thanks a lot and best regards !

    @Controller
    @RequestMapping(value="/FileUploadForm.htm")
    public class UploadFormController implements HandlerExceptionResolver
    {//this is the Exception Handler and Controller class
        @RequestMapping(method=RequestMethod.GET)
    public String showForm(ModelMap model){
        UploadForm form = new UploadForm();
        model.addAttribute("FORM", form);
        return "FileUploadForm";
    }

    @RequestMapping(method=RequestMethod.POST)
    public String processForm(@ModelAttribute(value="FORM") UploadForm form,BindingResult result){
        if(!result.hasErrors()){
            FileOutputStream outputStream = null;
            String filePath = System.getProperty("java.io.tmpdir") + "/" + form.getFile().getOriginalFilename();
            try {
                outputStream = new FileOutputStream(new File(filePath));
                outputStream.write(form.getFile().getFileItem().get());
                outputStream.close();
            } catch (Exception e) {
                System.out.println("Error while saving file");
                return "FileUploadForm";
            }
            return "success";
        }else{
            return "FileUploadForm";
        }
    }

//MaxUploadSizeExceededException can be catched here.....but twice..
//then some weird happend, the connection between browser and server is broken...
    @Override
    public ModelAndView resolveException(HttpServletRequest arg0,
    HttpServletResponse arg1, Object arg2, Exception exception) {
        Map<Object, Object> model = new HashMap<Object, Object>();
        if (exception instanceof MaxUploadSizeExceededException){
            model.put("errors", "File size should be less then "+
            ((MaxUploadSizeExceededException)exception).getMaxUploadSize()+" byte.");
        } else{
            model.put("errors", "Unexpected error: " + exception.getMessage());
        }
        model.put("FORM", new UploadForm());
        return new ModelAndView("/FileUploadForm", (Map) model);//the programme can run to this line and return a ModelAndView object normally
    }
}
Jimson
  • 81
  • 2
  • 10
  • There is a WAR package at bottom of the article. Please deploy it into a brand new tomcat ,then upload a large file, and the problem that I metioned will show up. Is this a SpringMVC bug or what ??? – Jimson Mar 19 '15 at 04:01

2 Answers2

6

I've confirmed that the problem I met is a mechanism of Tomcat7/8 for an aborted upload request. A new attribute "maxSwallowSize" is the key to deal this situation. It should happen when you upload a file which is larger than 2M.

Because the 2M is the default value of this new attribute . Tomcat7/8 can't swallow the rest file bytes which is being uploaded from browser, so it simply dissconnect the connection. Please visit http://tomcat.apache.org/tomcat-8.0-doc/config/http.html and search for "maxSwallowSize".

Jimson
  • 81
  • 2
  • 10
1

Change CommonsMultipartResolver configuration to use a larger upload size. For example, the following line will set the maximum upload size to 100MB.

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

If you use a web server between the browser and Tomcat, make sure to change the upload size and connection timeout on the web server as well, otherwise the request may time out before reaching Tomcat.

manish
  • 19,695
  • 5
  • 67
  • 91
  • Thanks for your reply. But I'm sorry it's not very helpful. In fact I need to limit the maximum upload size to 100k . When I upload a large file , for example 5000k , then the problem will occur: the connection between browser and server would be broken. The browser reports an ERR_CONNECTION_RESET error. – Jimson Mar 18 '15 at 05:54
  • I took the WAR file you have pointed to, deployed it to a fresh Tomcat 8.0.20 installation on a Windows 7 Professional laptop and the application just works fine. A [screenshot](http://imgur.com/qLFPBjB) from Chrome and Opera (Chrome on the left, Opera on the right). I changed the maximum file size to 1 byte and uploaded an Excel sheet for the test. – manish Mar 19 '15 at 10:39
  • 1
    I've confirmed that the problem I met is a mechanism of Tomcat7/8 for an aborted upload request. A new attribute "maxSwallowSize" is the key to deal this situation. It should happen when you upload a file which is larger than 2M – Jimson Mar 25 '15 at 09:06
  • Because the 2M is the default value of this new attribute . Tomcat7/8 can't swallow the rest file bytes which is being uploaded from browser, so it simply dissconnect the connection. Please visit http://tomcat.apache.org/tomcat-8.0-doc/config/http.html and search for "maxSwallowSize". And you can do more test on a slow speed network if convenient. :) – Jimson Mar 25 '15 at 09:13
  • Good that you got to the root cause. You should add your findings as an answer to this question and accept it as the answer so that others who come across this post in the future can benefit from it. – manish Mar 25 '15 at 21:31