1. 问题现象
在开发环境上传图片正常,但部署到 Linux 后,通过浏览器上传图片时,前端提示:
Request failed with status code 413HTTP 状态码 413 Request Entity Too Large 表示服务端或请求链路中的某一层拒绝接收过大的 HTTP 请求体。它通常不是图片格式、文件保存路径或对象存储连接的问题。
2. 优先判断请求被哪一层拦截
上传链路通常如下:
浏览器 -> CDN/WAF/负载均衡/API 网关/Ingress -> Nginx -> Spring Boot -> 文件存储413 可能由链路中任意一层返回。应先判断请求是否已进入应用:
- 在浏览器开发者工具的 Network 面板查看响应头和响应体。
- 查看 Nginx
access.log和error.log。 - 查看 Spring Boot 的访问日志、应用日志和 traceId 日志。
若 Nginx 错误日志出现以下内容,说明请求在 Nginx 被拒绝,尚未转发到 Spring Boot:
client intended to send too large body若应用没有对应请求日志,也可作为请求未到达应用的佐证。
3. 常见根因:Nginx 默认只允许 1MB 请求体
Nginx 未配置 client_max_body_size 时,默认限制为 1m。因此,即使 Spring Boot、前端或文件存储允许更大文件,Nginx 仍会先返回 413。
下面的反向代理配置没有设置请求体上限,因此会使用默认的 1m:
location /api/ {
proxy_pass http://127.0.0.1:9080;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto https;
}4. 不要只按原图片大小估算
有些系统不使用 multipart/form-data 上传文件,而是将文件转为 Base64 后写入 JSON 请求体;若 API 又对整个 JSON 请求体进行加密和 Base64 封装,实际 HTTP 请求体会显著大于原始文件。
本项目的通用上传接口为 JSON 请求体,其中包含 fileBase64 字段;非登录 API 还会经过 SM4 加密和安全信封封装。因此,近似关系为:
原始图片大小
* 4 / 3 (图片转 Base64)
* 4 / 3 (加密后的请求数据再次 Base64)
= 约 1.78 倍原始图片大小JSON 字段、签名、随机数和填充会额外增加少量字节。以原图大小为 10MB 为例,最终 HTTP 请求体约为 17.8MB,不能将 Nginx 上限仅设置为 10m 或 15m。
5. 推荐的 Nginx 配置
若图片原图业务上限为 10MB,建议将上传相关 API 的 Nginx 请求体限制设置为 30m,为加密封装和后续调整保留余量。
5.1 按 /api/ 路径配置
适用于同一 API 前缀下存在多种受控上传接口的场景:
location /api/ {
client_max_body_size 30m;
proxy_pass http://127.0.0.1:9080;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto https;
}5.2 仅按上传接口配置
若希望更严格地控制其他 API 的请求体大小,可为上传接口建立更精确的 location,并保留普通 API 的原有限制:
location = /api/system/uploads {
client_max_body_size 30m;
proxy_pass http://127.0.0.1:9080;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto https;
}
location /api/ {
proxy_pass http://127.0.0.1:9080;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto https;
}location = /api/system/uploads 是精确匹配,优先级高于 location /api/。对于上传接口的子路径,例如文件列表、回收站操作,仍会使用 /api/ 的规则;它们通常不包含大文件请求体。
6. 生效和验证
修改配置后,先校验语法,再平滑重载:
nginx -t
nginx -s reload也可以使用 systemd:
systemctl reload nginx验证时应选择接近业务上限的真实图片,并同时确认:
- 浏览器 Network 面板中上传请求返回
2xx,不再是413。 - Nginx
error.log不再出现client intended to send too large body。 - Spring Boot 收到请求并返回业务结果。
- 上传后的图片可正常访问,且文件大小、格式和场景限制仍由应用层校验。
7. 不要误用 Spring multipart 配置
下面的 Spring Boot 配置只对 multipart/form-data 请求生效:
spring:
servlet:
multipart:
max-file-size: 100MB
max-request-size: 100MB如果上传接口通过 @RequestBody 接收 JSON 和 Base64 数据,这些 multipart 限制并不能解除 Nginx 返回的 413。同理,server.tomcat.max-http-form-post-size 是表单 POST 限制,也不是该问题的直接修复手段。
应用层仍应保留按上传场景、文件类型和原始文件字节数执行的大小校验;Nginx 的 client_max_body_size 只负责允许足够大的加密请求体抵达应用。
8. 上游还有网关时的检查项
即使 Nginx 已设置 30m,若其前方仍存在其他入口组件,也必须逐层确认请求体限制不低于该值:
| 组件 | 重点配置或检查项 |
|---|---|
| Kubernetes NGINX Ingress | nginx.ingress.kubernetes.io/proxy-body-size: "30m" |
| API 网关 | 请求体大小或 payload size 限制 |
| WAF/CDN | 上传请求大小、POST body 大小策略 |
| 负载均衡 | HTTP 请求体或代理上传限制 |
| 对象存储直传 | 预签名上传策略和对象大小策略 |
最终有效限制由最小值决定。排查时应从浏览器请求开始,沿实际转发路径逐层核对,而不是仅修改其中一个 Nginx 配置文件。
9. 安全建议
不建议将 client_max_body_size 配置为 0(无限制)或设置成与业务无关的超大值。应遵循以下原则:
- 根据原文件上限和编码/加密膨胀比例计算入口限制。
- 优先仅对上传路径放宽限制,避免所有 API 都接受大请求体。
- 保留前端预校验、应用层文件大小校验、文件类型白名单和权限校验。
- 对大文件或高频上传场景补充网关限流、超时和监控告警。
- 当文件规模持续增大时,优先采用对象存储预签名直传,减少大文件经过应用网关和 JSON 加密接口的开销。
10. 结论
Linux 环境上传图片出现 413 时,首先检查入口代理的请求体上限。对于 Base64 + 接口加密的上传链路,应按实际 HTTP 请求体而不是原始文件大小计算容量。对本项目 10MB 图片上传场景,在 Nginx 上传 API 路径配置 client_max_body_size 30m;,并同步核对上游网关限制,是解决该问题的直接方案。
评论
0成为第一个留下想法的人。