When a <multipart-config> element is present without any <file-size-threshold> child element, the whole <multipart-config> appears to be ignored. Specifying <file-size-threshold>0</file-size-threshold> (which is the default) results in expected behavior. With sample configuration: <multipart-config> <max-file-size>1048576</max-file-size><!-- 1MiB --> <max-request-size>1049600</max-request-size><!-- 1 MiB + 1 kiB --> <file-size-threshold>1024</file-size-threshold><!-- 1KiB --> </multipart-config> File sizes larger than 1MiB are rejected as expected. Removing the <file-size-threshold> element completely causes large files to be accepted as if the configuration were not there. Attaching a debugger, I can see that the multipartConfigElement is essentially all defaults: multipartConfigElement MultipartConfigElement (id=545) fileSizeThreshold 0 location "" (id=550) maxFileSize -1 maxRequestSize -1
Created attachment 37198 [details] Sample WAR file which reproduces the issue This WAR file (including source) will work as expected: 1. Deploy the WAR file 2. Navigate to /test which will load index.html 3. Choose an arbitrary file and upload 4a. A small enough file will yield a debug output 4b. A large enough file (> 1MiB) will cause an error If you edit WEB-INF/web.xml to remove the <file-size-threshold>, you will be able to upload any size file without error.
Ok, ok, the check here looks inaccurate: https://github.com/apache/tomcat/blob/master/java/org/apache/catalina/startup/ContextConfig.java#L1365 Unless all are set, only the location would be used.
I think I've found the problem, at ContextConfig:1355: 1355 MultipartDef multipartdef = servlet.getMultipartDef(); 1356 if (multipartdef != null) { 1357 if (multipartdef.getMaxFileSize() != null && 1358 multipartdef.getMaxRequestSize()!= null && 1359 multipartdef.getFileSizeThreshold() != null) { 1360 wrapper.setMultipartConfigElement(new MultipartConfigElement( multipartdef.getLocation(), Long.parseLong(multipartdef.getMaxFileSize()), Long.parseLong(multipartdef.getMaxRequestSize()), Integer.parseInt( multipartdef.getFileSizeThreshold()))); } else { wrapper.setMultipartConfigElement(new MultipartConfigElement( multipartdef.getLocation())); } } When execution reaches 1355, the MultipartDef object contains the expected values: maxFileSize=1048576 maxRequestSize=1049600 fileSizeThreshold=null The predicate on lines 1357 - 1359 cause this configuration to not be applied if any of the items are missing. The servlet spec allows any of these items to be missing, so I believe this is a bug and spec violation together in one.
Created attachment 37199 [details] Proposed patch
Updating description to reflect the fact that any missing element can cause this.
Initial testing indicates this patch is correct. I'll commit once I build a proper test-case. My guess is that this will not affect uses of @MultipartConfig annotation, as this bug occurs when copying the web.xml config to the live servlet (wrapper) object. Temporary workaround for anyone observing lack of <multipart-config>: Make sure to specify all of max-file-size, max-request-size, file-size-threshold
Fixed in trunk (tc10) in commit 8dddc11512fbd3b91ed9d737a42e4b8415458ddf Working on my git-fu to back-port to other supported branches.
Rémy has back-ported to 9.0.x and 8.5.x.