Fork me on GitHub
03 August 2022

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 当然也实现了该规范,流程看下图

ApplicationServletRegistrationApplicationServletRegistrationStandardWrapperStandardWrapperRequestRequestsetMultipartConfiggetParts()getMultipartConfigElement()MultipartConfigElement

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,要修改该配置它只能从两方面入手:

  1. 注入 MultipartConfigElement
  2. 修改 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 配置,它优先级高且普适性更好。