Spring file upload and connection reset issue
A Spring servlet initializer to configure the file upload limit, 5mb per file and 10mb per request.
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
- Spring 4.3.5.RELEASE
- Tomcat 8
- 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
<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
<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.
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.
thanks, it’s working finally🤯
You are the best!!
It was real helpful to me. Thank you.
Hi Mkyong, ur posts are very conducive to me. I am in same issue nowadays but i doubt that the server side may be websphere or Glassfish or tomcat. Although i m receiving same error “Error writing request body to server”…. Can You Kindly tell me whats counterpart property of Tomcat:MaxSwallowSize in Websphere and in Glassfish respectively????
Really good solution to use both javascript and server check
Hello I am Cho Soon-tae, who has read your website in Korea and solved the same problem.
Thank you for leaving a good example. If you have any ideas other than 2 ideas, I would appreciate your link.
I have processed it as 1 solution first.
Thank you.
Hi,
What do you suggest if I want to allow far more file size upload in production ?
Thanks for this article
very good! it really helps!