上传文件为什么报 413?1MB 的限制到底是单个文件还是整个请求?为什么一个只有 51 个小字段的表单也会 413?getOriginalFilename 能不能直接拿来存盘?这篇在 Spring Boot 4.0.8 的内嵌 Tomcat 11 上用真实的 multipart 请求逐个验证。
100 KB 文件 + 文本字段 note → 200 name=a.bin size=100000 read=100000 note=hello 同名多个文件 files(3 个) → 200 files=3 sizes=[10, 20, 30] 文件名含路径 ../../etc/passwd → 200 originalFilename=[../../etc/passwd] 文件名含 Windows 路径 C:\\dir\\a.txt → 200 originalFilename=[C:\dir\a.txt] 没带 file 部分(required=false) → 200 file=null 带了 file 但 0 字节 → 200 file=empty.txt:0(isEmpty) 带了 file 部分但文件名为空 → 200 file=:3 没带 file(required=true) → 400 [MissingServletRequestPartException] Required part 'file' is not present.
文件名不会被清洗;0 字节文件不是 null;缺失的 file 部分按 required 决定。
文件 1,000,000 字节(1MB 以内) → 200 name=a size=1000000 read=1000000 note=null 文件 1,048,576 字节(正好 1MB) → 200 name=a size=1048576 read=1048576 note=null 文件 1,048,577 字节(超 1 字节) → 413 [Connection: close, Content-Length: 0] 文件 2 MB → 413 [Connection: close, Content-Length: 0] 3 个文件各 900 KB,共 2.7 MB(单个都没超 1MB) → 200 files=3 sizes=[900000, 900000, 900000] 12 个文件各 900 KB,共 10.8 MB(总量超 10MB) → 413 [Connection: close, Content-Length: 0](客户端还没发完,连接已被服务端关闭:BrokenPipeError)
单个文件 1MB,整个请求 10MB;413 响应体为空。
文件 3 MB → 200 name=a size=3000000 read=3000000 note=null 文件 6 MB(超 max-file-size=5MB) → 413 [Connection: close, Content-Length: 0] 3 个文件各 4MB 共 12MB(总量超 max-request-size=10MB) → 413 [Connection: close, Content-Length: 0](客户端还没发完,连接已被服务端关闭:BrokenPipeError)
两个上限各管各的。
限制 -1(不限制):50 MB 文件 → 200 name=big size=50000000 read=50000000 note=null
-1 可以关掉限制,但要自己守住资源。
不是 multipart 的普通表单请求发到上传接口 → 400 [MissingServletRequestParameterException] Required request parameter 'note' for method parameter type String is not present multipart.enabled=false 时发 multipart → 400 [MultipartException] Failed to parse multipart servlet request
enabled=false 之后上传接口不可用。
10 个只有 1 字节的文本字段(整个请求不到 1 KB) → 200 parts=10 50 个只有 1 字节的文本字段(整个请求不到 1 KB) → 200 parts=50 51 个只有 1 字节的文本字段(整个请求不到 1 KB) → 413 [Connection: close, Content-Length: 0] 100 个只有 1 字节的文本字段(整个请求不到 1 KB) → 413 [Connection: close, Content-Length: 0] 51 个部分,其中 1 个是文件 → 413 [Connection: close, Content-Length: 0]
默认 50 个部分,文本字段也算。
50 个文本字段 → 200 parts=50 200 个文本字段 → 200 parts=200 201 个文本字段 → 413 [Connection: close, Content-Length: 0]
由 server.tomcat.max-part-count 控制。