Spring file upload and connection reset issue

摘要: A Spring servlet initializer to configure the file upload limit, 5mb per file and 10mb per request.

A Spring servlet initializer to configure the file upload limit, 5mb per file and 10mb per request.

MyWebInitializer.java
public class MyWebInitializer extends
        AbstractAnnotationConfigDispatcherServletInitializer {
    private int maxUploadSizeInMb = 5 * 1024 * 1024; // 5 MB
    //...
    @Override
    protected void customizeRegistration(ServletRegistration.Dynamic registration) {
        // upload temp file will put here
        File uploadDirectory = new File(System.getProperty("java.io.tmpdir"));
        // register a MultipartConfigElement
        MultipartConfigElement multipartConfigElement =
                new MultipartConfigElement(uploadDirectory.getAbsolutePath(),
                        maxUploadSizeInMb, maxUploadSizeInMb * 2, maxUploadSizeInMb / 2);
        registration.setMultipartConfig(multipartConfigElement);

If you try to upload a file size bigger than the upload limit, let says 20mb, the following weird “connection resets” error will be displayed:

Even the global @ControllerAdvice can’t catch the above exception!

Tested

  1. Spring 4.3.5.RELEASE
  2. Tomcat 8
  3. Spring MVC file upload example

1. Solution

After a few days of investigation and research, I find out the problem was not related to Spring (no problem if deployed to Jetty), it’s the Tomcat default connector maxSwallowSize

Quote – Apache Tomcat 8 Configuration Reference

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.

If you try to upload a file size, which exceeded the size limit, Tomcat will crop it at the default 2mb and reset the connection. To solve it quickly, put a -1 (unlimited) for maxSwallowSize

Tomcat/conf/server.xml
    <Connector port="8080" protocol="HTTP/1.1"
               connectionTimeout="20000"
               redirectPort="8443"
               maxSwallowSize="-1" />

This -1 is good for development, but not for production, if user tries to upload a 100mb file, Tomcat will waste resources to handle the extra bandwidth.

2. Idea

2. 1 Try to put a reasonable limit for the file upload, for example, 11mb (11 x 1024 x 1024 = bytes) in this example

Tomcat/conf/server.xml
    <Connector port="8080" protocol="HTTP/1.1"
               connectionTimeout="20000"
               redirectPort="8443"
               maxSwallowSize="11534336" />

2.2 And implement a Javascript to check the file size before the upload.

What about Jetty?
Tested with Jetty 9, can’t find out any maxSwallowSize setting, and it will NOT cause a connection reset if the file size has exceeded the upload limit.

References

  1. Apache Tomcat 8 Configuration Reference
  2. Setting a tomcat property using spring boot application properties
  3. Spring MVC file upload example

上一篇: Spring MVC file upload example Commons FileUpload
下一篇: Eclipse Ctrl + T in IntelliJ IDEA
 评论 ( What Do You Think )
名称
邮箱
网址
评论
验证
   
 

 


  • 微信公众号

  • 我的微信

站点声明:

1、一号门博客CMS,由Python, MySQL, Nginx, Wsgi 强力驱动

2、部分文章或者资源来源于互联网, 有时候很难判断是否侵权, 若有侵权, 请联系邮箱:summer@yihaomen.com, 同时欢迎大家注册用户,主动发布无版权争议的 文章/资源.

3、鄂ICP备14001754号-3, 鄂公网安备 42280202422812号