nginx-413-client-max-body-size

Nginx 413 排错:client_max_body_size 加在哪一层才生效

现象

上传一个 20 多 MB 的附件,前端直接弹 413:

复制代码
413 Request Entity Too Large
nginx/1.20.2

不是超时,也不是网络中断,请求压根没进后端。

环境

  • 链路:浏览器 → Nginx(443) → 反向代理 → Spring Boot(8080)
  • 站点配置在 /etc/nginx/conf.d/app.conf
  • 后端 spring.servlet.multipart.max-request-size 早就调到 100MB 了

后端限制已经放开,所以问题不在 Java 这边。

先确认是 Nginx 拦的

这一步别跳。判断方法很简单:去看后端访问日志。

413 是 Nginx 读完请求头、发现 Content-Length 超限就直接返回的,请求不会转发给 upstream。所以如果这次上传在 Spring Boot 的 access log 里完全没有记录,而错误页又是标准的 Nginx 样式、响应头带 Server: nginx,那就基本确定拦在 Nginx 层了。

Nginx 自己的 error.log 里会留一句:

复制代码
client intended to send too large body: 25165824 bytes

看到这句就不用再怀疑了。

另外,如果这个请求是 JSON 而不是文件,client_max_body_size 一样管,它不是只针对 multipart 上传的。

加在哪

client_max_body_size 只能写在三个地方:http、server、location。作用域越小优先级越高,也就是 location > server > http。

想让整个站点生效,写在 server 块的大括号里面 ,和 listen、server_name 同级,别写进 location:

nginx 复制代码
server {
    listen 443 ssl;
    server_name example.com;

    client_max_body_size 100m;

    root /www/wwwroot/example;
    index index.html;

    location / {
        try_files $uri $uri/ /index.php?$query_string;
    }
}

写在 server 块里的哪一行其实无所谓,Nginx 不靠顺序解析这个指令。我习惯塞在 server_name 下面,改的时候一眼能找到。

几个容易写错的位置:

  • 写进 http {} 外面或者 events {} 里 ------ nginx -t 直接报错,指令不允许出现在那儿
  • 写进某个 location 里 ------ 只对匹配这个 location 的请求生效,其他路径还是默认的 1m
  • 同一个 server 块里写了两次 ------ 报 "client_max_body_size" directive is duplicate,改之前先 grep 一下有没有旧值

只想放开上传接口

那就别在 server 层放大,收窄到具体路径更安全:

nginx 复制代码
server {
    listen 443 ssl;
    server_name example.com;

    location /api/upload {
        client_max_body_size 100m;
        proxy_pass http://127.0.0.1:8080;
    }
}

全站放开 100m 意味着任何一个接口都能被打 100MB 的包,能收窄就收窄。

所有站点统一放开

写在 nginx.conf 的 http 块里:

nginx 复制代码
http {
    client_max_body_size 100m;

    include /etc/nginx/conf.d/*.conf;
}

之后某个站点想单独收紧,在它的 server 块里再写一次小的值就行。

改完别忘了这一步

bash 复制代码
nginx -t
nginx -s reload

nginx -t 一定要跑,配置写错位置它会直接告诉你哪一行。

还是 413

reload 之后仍然 413,按这个顺序查:

  1. 改的不是那台 Nginx。 链路里可能还有一层:CDN、WAF、SLB,或者前面还架着一台反代。看错误页样式和 Server 响应头,是谁返回的就改谁。这是最常见的原因。
  2. 80 和 443 两个 server 块。 只改了监听 80 的那个,实际流量走的是 443 的块,等于没改。
  3. 后端自己的限制。 Nginx 放行之后请求才轮到应用,PHP 的 post_max_size、upload_max_filesize,Tomcat 的 maxPostSize,Express 的 express.json({ limit }),各自还得对上。
  4. 面板改错地方。 用宝塔的话在「网站 → 设置 → 配置文件」里改,改完在面板里重载,别直接手改 /www/server/nginx/conf/nginx.conf 就以为生效了。

有没有必要把限制调得很大

不建议。真要传大文件,比堆 client_max_body_size 靠谱的做法是:

  • 前端先压缩,或者分片上传 + 断点续传
  • 走对象存储预签名 URL 直传,body 根本不过自己的 Nginx
  • 流式处理,别把整个 body 一次性读进内存

这个阀门存在的意义就是挡恶意大包,图省事设成 0(等于关掉检查),迟早要在别的地方还回来。

附:各层对应的参数

排查的时候对着找就行:

层级 配置
Nginx client_max_body_size 100m;
Apache LimitRequestBody 104857600(单位字节)
PHP upload_max_filesize = 100M、post_max_size = 100M(后者要大于前者)
Spring Boot spring.servlet.multipart.max-file-size、max-request-size
Tomcat maxPostSize、maxSwallowSize
Node/Express express.json({ limit: '100mb' })、multer 的 limits.fileSize
云网关/CDN API Gateway、Cloudflare、WAF、ALB 各有各的请求体上限
相关推荐
qqxiaoxingxing8 小时前
HR重复性工作自动化落地指南:先梳理任务边界,再选工具
运维·自动化
王琦03189 小时前
持续集成持续交付企业示例
运维·ci/cd
Lsetea9 小时前
SSL证书指纹相同但文件哈希不同:PEM、DER与公钥摘要怎么比
运维·https·ssl证书·openssl·证书链
wtblszn9 小时前
废气处理余热回收设备远程运维系统方案
运维
乔旭伟10 小时前
Linux 服务器备份实战:一致性快照、日志归档与恢复演练
linux·运维·服务器
cpolar技术支持10 小时前
把配置发出去怕带出密钥?先把含凭据配置转成脱敏只读快照,用 cpolar 给同事核对差异
运维·python·内网穿透·cpolar·配置脱敏
我不会起名字32210 小时前
Redis 突然只能读不能写:MISCONF 报错的 3 类触发条件与 4 步恢复
运维·redis·持久化·排查·misconf
workflower11 小时前
Agentic AI 时代的企业ICT 基础设施运维
运维·人工智能·机器学习·重构·云计算·汽车
szxinmai主板定制专家11 小时前
ZYNQ 数据采集方案踩坑总结:电力强电磁干扰、工业现场多协议适配优化
运维·人工智能·fpga开发·机器人·zynq
猫咪很可爱11 小时前
Oracle RAC 启动失败排查:私网通信与内核参数优化实战
运维·数据库·oracle