Spring Boot升级Tomcat至9.0.31后Multipart文件上传失败求助
我之前也碰到过一模一样的情况,Tomcat 9.0.31的安全更新确实给Multipart上传带来了兼容性坑,咱们一步步来搞定:
问题根源
Tomcat 9.0.31修复了包括CVE-2020-1938在内的多个安全漏洞,其中对Multipart请求的校验逻辑做了严格强化。当请求的Content-Length与实际上传流的长度不匹配时,Tomcat会直接抛出Stream ended unexpectedly异常;而旧版本Tomcat(比如9.0.30)会忽略这种不一致,继续处理请求,这就是为什么旧版本能正常运行的原因。
解决方案
1. 升级Spring Boot到兼容版本
Spring Boot官方在2.2.5.RELEASE及后续版本中已经针对Tomcat 9.0.31的这个兼容性问题做了修复。如果你当前用的是低于2.2.5.RELEASE的Spring Boot版本,直接升级到同系列的最新稳定版(比如2.2.x分支的最新版),就能直接解决问题,这也是最推荐的方案。
2. 调整Tomcat的maxSwallowSize配置
如果暂时没法升级Spring Boot,可以通过修改Tomcat的maxSwallowSize参数绕过这个严格校验:
方式一:通过Spring Boot配置文件
在application.properties里添加:
server.tomcat.max-swallow-size=-1
如果用YAML格式的application.yml,就写:
server: tomcat: max-swallow-size: -1
这个配置会让Tomcat允许“吞掉”长度不匹配的请求流,避免抛出异常。
方式二:自定义Tomcat连接器配置
如果需要更灵活的控制,可以创建一个配置类自定义Tomcat的连接器:
import org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory; import org.springframework.boot.web.server.WebServerFactoryCustomizer; import org.springframework.stereotype.Component; import org.apache.catalina.connector.Connector; import org.apache.coyote.AbstractHttp11Protocol; @Component public class TomcatMultipartFixCustomizer implements WebServerFactoryCustomizer<TomcatServletWebServerFactory> { @Override public void customize(TomcatServletWebServerFactory factory) { factory.addConnectorCustomizers((Connector connector) -> { if (connector.getProtocolHandler() instanceof AbstractHttp11Protocol) { // 设置maxSwallowSize为-1,禁用长度校验限制 ((AbstractHttp11Protocol<?>) connector.getProtocolHandler()).setMaxSwallowSize(-1); } }); } }
3. 检查客户端请求的正确性
还要确认上传文件的客户端有没有正确设置Content-Length请求头,且该值和实际文件大小完全一致。如果客户端用了分块编码(Chunked Transfer-Encoding),也要检查分块逻辑是否正确,避免流提前终止。
验证
修改完配置后重启应用,再测试Multipart文件上传功能,应该就能正常运行了。
内容的提问来源于stack exchange,提问作者Anoop M Nair

