如何在Spring Boot内嵌Tomcat中配置最大文件数量?
如何为Spring Boot内嵌Tomcat配置多文件上传的最大文件数量?
我们的微服务基于Spring Boot + Java开发,使用内嵌Tomcat服务器,原本可通过以下配置项控制文件上传大小:
spring.servlet.multipart.max-file-size=10MB spring.servlet.multipart.max-request-size=10MB
但针对Tomcat的相关CVE要求配置最大文件数量参数,以下是具体的解决思路和实现方案:
现状说明
- Spring Boot官方的
spring.servlet.multipart系列配置中无直接对应最大文件数量的参数; - 查看Tomcat 9.0.75版本的
MultipartConfigElement,仅包含maxFileSize、maxRequestSize、fileSizeThreshold三个属性,无文件数量相关配置; MultipartConfigFactory确实没有setMaxFileCount方法,无法通过该类直接配置。
可行解决方案
方案一:自定义MultipartResolver做业务层拦截
通过继承Spring的CommonsMultipartResolver(或StandardServletMultipartResolver),在解析请求时统计上传文件数量,超过阈值则抛出异常,实现方式如下:
1. 自定义MultipartResolver子类
import org.springframework.web.multipart.MultipartException; import org.springframework.web.multipart.MultipartHttpServletRequest; import org.springframework.web.multipart.commons.CommonsMultipartResolver; import javax.servlet.http.HttpServletRequest; import java.util.List; public class LimitedMultipartResolver extends CommonsMultipartResolver { private int maxFileCount = 10; // 默认限制10个文件 public void setMaxFileCount(int maxFileCount) { this.maxFileCount = maxFileCount; } @Override protected MultipartHttpServletRequest doResolveMultipart(HttpServletRequest request) throws MultipartException { MultipartHttpServletRequest multipartRequest = super.doResolveMultipart(request); List<String> fileNames = multipartRequest.getFileNames(); if (fileNames.size() > maxFileCount) { throw new MultipartException(String.format("上传文件数量超过限制,最多允许%d个文件", maxFileCount)); } return multipartRequest; } }
2. 配置自定义Resolver为Spring Bean
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.web.multipart.MultipartResolver; @Configuration public class MultipartConfig { @Bean public MultipartResolver multipartResolver() { LimitedMultipartResolver resolver = new LimitedMultipartResolver(); resolver.setMaxFileCount(10); // 设置最大文件数量 // 同时配置文件大小限制,替代原spring.servlet.multipart配置 resolver.setMaxUploadSize(124 * 1024 * 1024); // 对应max-request-size(124MB) resolver.setMaxUploadSizePerFile(124 * 1024 * 1024); // 对应max-file-size(124MB) return resolver; } }
方案二:自定义Tomcat Valve做底层拦截
如果需要在Tomcat层面全局拦截所有multipart请求,可自定义Valve实现文件数量校验:
1. 自定义Tomcat Valve
import org.apache.catalina.connector.Request; import org.apache.catalina.connector.Response; import org.apache.catalina.valves.ValveBase; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import java.io.IOException; public class MultipartFileCountValve extends ValveBase { private int maxFileCount = 10; public void setMaxFileCount(int maxFileCount) { this.maxFileCount = maxFileCount; } @Override public void invoke(Request request, Response response) throws IOException, ServletException { HttpServletRequest httpRequest = request.getRequest(); if (httpRequest.getContentType() != null && httpRequest.getContentType().startsWith("multipart/")) { try { request.parseParts(); // 统计文件类型的part数量 int fileCount = (int) request.getParts().stream() .filter(part -> part.getContentType() != null && !part.getSubmittedFileName().isBlank()) .count(); if (fileCount > maxFileCount) { response.sendError(400, String.format("上传文件数量超过限制,最多允许%d个文件", maxFileCount)); return; } } catch (Exception e) { response.sendError(400, "文件上传解析失败"); return; } } getNext().invoke(request, response); } }
2. 配置Tomcat加载自定义Valve
import org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory; import org.springframework.boot.web.server.WebServerFactoryCustomizer; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @Configuration public class TomcatConfig { @Bean public WebServerFactoryCustomizer<TomcatServletWebServerFactory> tomcatMultipartValveCustomizer() { return factory -> { MultipartFileCountValve fileCountValve = new MultipartFileCountValve(); fileCountValve.setMaxFileCount(10); factory.addEngineValves(fileCountValve); }; } }
方案选择建议
- 方案一更贴合Spring Boot开发模式,对业务代码侵入小,无需关注Tomcat底层细节,推荐优先使用;
- 方案二适合需要全局拦截所有multipart请求的场景,但需注意请求解析顺序,避免与Spring的MultipartResolver逻辑冲突。
内容的提问来源于stack exchange,提问作者Joe Soule
相关产品推荐
相关产品推荐

