Spring Boot 如何限制上传文件大小
Spring Boot 项目中会使用 spring.servlet.multipart.max-file-size
来修改上传文件大小,默认为 1MB。那它是如何影响 Tomcat 的?
Servlet 规范中上传文件相关定义:
javax.servlet.ServletRegistration.Dynamic#setMultipartConfig
javax.servlet.MultipartConfigElement
javax.servlet.http.HttpServletRequest#getParts
Tomcat 当然也实现了该规范,流程看下图
Request#getParts
在解析上传文件时调用 parseParts
,读取 MultipartConfigElement
相关配置,先从 Servlet 容器中获取,如不存在则从 Connector(可以理解为全局配置类) 获取,实现代码如下:
// org.apache.catalina.connector.Request#parseParts
private void parseParts(boolean explicit) {
...
MultipartConfigElement mce = getWrapper().getMultipartConfigElement();
if (mce == null) {
if(context.getAllowCasualMultipartParsing()) {
// 未通过 Dynamic#setMultipartConfig 配置 MultipartConfigElement 时
// 从 connector 中读取
mce = new MultipartConfigElement(null, connector.getMaxPostSize(),
connector.getMaxPostSize(), connector.getMaxPostSize());
} else {
if (explicit) {
partsParseException = new IllegalStateException(
sm.getString("coyoteRequest.noMultipartConfig"));
return;
} else {
parts = Collections.emptyList();
return;
}
}
}
...
}
Connector 的配置 org.apache.catalina.connector.Connector#maxPostSize
默认为 2MB。
综上,当未配置 MultipartConfigElement 时默认大小为 2MB。
了解到 Tomcat 的配置后再来看 Spring Boot,要修改该配置它只能从两方面入手:
- 注入 MultipartConfigElement
- 修改 Connector#maxPostSize
1. 注入 MultipartConfigElement
spring.servlet.multipart.max-file-size
对应的自动配置类为 MultipartAutoConfiguration
,它会创建 javax.servlet.MultipartConfigElement
实例。接下来 ServletContextInitializerBeans.ServletRegistrationBeanAdapter#createRegistrationBean
创建 RegistrationBean
,它会启动时自动把MultipartConfigElement
实例注入到 Tomcat 中,具体原理可参考 是时候抛弃web.xml了?
2. 修改 Connector#maxPostSize
配置项为 server.tomcat.max-http-form-post-size
,由 TomcatWebServerFactoryCustomizer
负责把该配置更新到 Connector#maxPostSize
总之,推荐使用 spring.servlet.multipart.max-file-size
配置,它优先级高且普适性更好。