Nginx 文件上传报 413 Request Entity Too Large 怎么办?
413 上传失败需先确认拒绝请求的层;Nginx 的 client_max_body_size 默认 1m,仅在它触发限制时调整;http/server/location 三级作用域、应用层与 PHP 配套限制、CDN 前置限制与 FAQ。
413 表示某一层拒绝了过大的请求体;若由 Nginx 的 client_max_body_size 触发,其默认值为 1m。先确认响应来源,再按业务请求体上限调整:
http {
client_max_body_size 100M; # 全局:http 块
}
# 或只给上传接口放开
location /upload {
client_max_body_size 500M; # location 级,就近优先
}
改完 nginx -t && systemctl reload nginx。
三级作用域
client_max_body_size 可以出现在 http、server、location 任意层级,内层覆盖外层。排障时用 nginx -T 看最终生效值——常见翻车是全局调大了,某个 location 里却单独写了个小值。
别忘了整条链路上的其他限制
Nginx 放行了不代表后面接得住,逐层对齐:
- PHP:
php.ini的upload_max_filesize(单文件)和post_max_size(整个 POST 体)需与业务限额协调,整个请求还包括 multipart 开销,不能直接把单文件值等同整个请求体;改完重启 PHP-FPM。 - 应用框架:Express
express.json({limit})限制 JSON 请求体,不是 multipart 文件上限;Spring 可配置spring.servlet.multipart.max-file-size。Django 的 DATA_UPLOAD_MAX_MEMORY_SIZE 主要限制请求中非文件数据,FILE_UPLOAD_MAX_MEMORY_SIZE 控制内存与临时文件切换,不是通用文件大小硬限额,应另做上传大小校验。 - 反向代理上游:上游若也是 Nginx 或别的网关,它还有一层限制。
- CDN/LB:需按实际产品、套餐和配置核对请求体上限,不能假定所有入口一致。
- 超时联动:大文件上传慢,顺手检查
client_body_timeout与上游超时,别 413 修好了改 504。
验证限额时,分别发送略低于和略高于阈值的请求,并检查每层入口的记录。把 Nginx 日志通过 DataKit接入观测云后,可按 URI 与 413 状态筛选受影响接口;请求体大小只有在日志中记录并解析了对应字段时才能查询,不能从 413 本身推算。
大文件的正确姿势
超过几百 MB 的上传,不建议硬穿应用服务器:用对象存储预签名 URL 让浏览器直传 OSS/S3,Nginx 和应用只处理小请求。可绕过应用反代的请求体路径,但仍受对象存储单次/分片限制、预签名权限及有效期约束。
常见问题(FAQ)
Q:client_max_body_size 设为 0 是无限制吗?
A:是——0 表示不检查。但等于敞开大门接受任意大小的请求体,内存/磁盘压力大增,生产环境不建议。
Q:改了还是 413,nginx -T 里值也对?
A:请求可能根本没到这台 Nginx——前面还有 CDN/SLB/另一层反代,413 是它们返回的。上游应用也可能返回 413;Server 头只能作线索,应对照每层访问/error 日志及 upstream_status。
Q:大 body 会占多少内存?
A:Nginx 默认把 body 缓冲到 client_body_buffer_size,超出写临时文件(client_body_temp_path)——实际资源受并发、缓冲配置与模块行为影响,不能保证不会耗尽内存;临时目录也要有足够磁盘。client_body_timeout 控制相邻读取的空闲间隔,不是上传总时长。