Reputation: 349
I'm experiencing strange behaviour when using Apache FileUpload with filesize limit and Tomcat web application server (version 9). Here's my code:
List<FileItem> multi = null;
try {
DiskFileItemFactory factory = new DiskFileItemFactory();
factory.setRepository(new File(System.getProperty("java.io.tmpdir")));
ServletFileUpload upload = new ServletFileUpload(factory);
upload.setFileSizeMax(2 * 1024 * 1024); // 2MB
upload.setHeaderEncoding("UTF-8");
multi = upload.parseRequest(request);
...
} catch (Exception e) {
e.printStackTrace();
}
// send servlet response
...
As visible above, the file size limit is 2MB.
If I upload a 1MB file, everything is OK, my servlet response is sent to client.
If I upload a 3MB file, behaviour is OK: the exception is thrown and my servlet response is sent to client.
If I upload a 10MB file, behaviour is NOT OK. The exception is thrown but my servlet response is never sent to client. WireShark shows me that tomcat respond with RST message and then client tries to send the request again and again.
After long debug, I could see that I could bypass the reset code (RST) by setting the maxSwallowSize
connector attribute (defined in server.xml
) to -1, or to a value bigger that 10MB.
Everything is OK if I remove setFileSizeMax()
call.
My questions are:
maxSwallowSize
when file is smaller/larger than limitUpvotes: 0
Views: 815
Reputation: 16045
First of all, since Servlet 3.0 (Tomcat 7.0), the functionality of commons-fileupload
is integrated into servlet containers: see HttpServletRequest#getParts
. You should consider using this API instead. Under the hood most servlet containers (including Tomcat) use a repackaged version of commons-fileupload
.
The maxSwallowSize
attribute of a connector tells Tomcat how many more bytes can the HTTP client send after your already finished processing the request, before Tomcat resets the TCP socket. In your case this means how many more bytes over the 2 MiB limit can the browser send.
This is a security measure: the HTTP protocol itself does allow the server to send an error response before receiving the complete request (see this question), but some browser do not comply with this (and in your case you don't send an error status). Try adding:
catch (SizeException e) {
response.setStatus(HttpServletResponse.SC_REQUEST_ENTITY_TOO_LARGE);
}
to your catch
clauses. If your browser complies in a timely fashion to the error status code, it will stop uploading before the maxSwallowSize
limit is reached and the client will display a 413
error page.
Upvotes: 1