后台上传一张高清图,或者用户提交一个附件,页面直接返回"413 Request Entity Too Large"。这个错误很直白:请求体(body)太大了,超出了服务器或中间环节允许的上限。它经常出现在用户上传大文件、提交长表单、走 API 传大 JSON 的场景。
413 的麻烦之处在于"限制可能藏在好几层":Nginx 有一层、PHP 有一层、后端框架自己还有一层,任何一层卡住都会返回 413,而且报错信息可能只暴露其中一层。这篇文章把这几层限制按顺序讲清楚,告诉你每层怎么查、怎么调,以及调大限制时有哪些安全风险。读完你能快速定位是哪一层在拦,并做出合理的调整,而不是盲目把所有值往大了改。
一、413 是哪一层拦的
一个上传请求通常会经过这些环节,每层都可能有大小限制:
| 环节 | 相关限制 | 默认常见值 |
|---|---|---|
| 客户端/浏览器 | 一般无硬限制,受表单配置影响 | — |
| CDN / WAF | 请求体大小限制 | 视产品配置 |
| Nginx | client_max_body_size |
1 MB |
| PHP-FPM | post_max_size / upload_max_filesize |
8M / 2M |
| 后端框架 | 各自的上传/请求体限制 | 视框架 |
| 应用逻辑 | 业务自己的文件大小校验 | 视业务 |
Nginx 的 client_max_body_size 默认是 1MB,这是最常被忽略的一层。很多人只在 PHP 里把 upload_max_filesize 调大了,结果发现还是 413,就是因为 Nginx 这层没改。
二、第一步:确认是不是 Nginx 拦的
Nginx 返回 413 时,错误日志里会有明确记录。
# 看错误日志里的 413 相关记录
sudo grep -i 'client intended to send too large body' /var/log/nginx/error.log | tail
# 更直接:看访问日志里 413 的请求
sudo awk '$9 == 413 {print $9, $7}' /var/log/nginx/access.log | sort | uniq -c | sort -rn
如果看到 client intended to send too large body: xxx bytes,基本可以确认是 Nginx 的 client_max_body_size 在拦。
调整方式(全局或站点级都可以,视需求选择):
# 方式一:http 段全局设置(影响所有站点)
http {
client_max_body_size 50m;
# ...
}
# 方式二:只在需要上传的 server 或 location 单独放开(推荐,影响面小)
server {
listen 443 ssl http2;
server_name example.com;
location /upload/ {
client_max_body_size 100m;
proxy_pass http://backend;
}
}
单纯调 client_max_body_size 还可能导致另一种问题:如果请求体超过 Nginx 缓冲区又没配置临时目录,Nginx 会写临时文件,client_body_temp_path 所在分区空间不足也会失败。一般默认目录够用,大文件场景可以确认一下:
client_body_temp_path /var/cache/nginx/client_temp; # http 段可选配置
client_body_buffer_size 128k; # 请求体缓冲区
改完配置一定要先测试语法再平滑重载:
sudo nginx -t && sudo systemctl reload nginx
三、第二步:确认 PHP 的限制
如果 Nginx 已经放开,页面还是报错(可能这次是 PHP 层面的报错而非 413),就要看 PHP 的两个关键配置。
# 查看 PHP 配置文件的路径(不同系统、不同 SAPI 位置不同)
php -i | grep -i 'Loaded Configuration File'
php -i | grep -iE 'post_max_size|upload_max_filesize|memory_limit|max_execution_time'
# 也可用 phpinfo() 页面查看,或直接看配置文件
# Debian/Ubuntu 常见:/etc/php/8.1/fpm/php.ini
# RHEL/CentOS/Rocky 常见:/etc/php.ini
三个参数各有分工,必须协调:
upload_max_filesize:单个上传文件的最大大小。post_max_size:整个 POST 请求体(含所有字段和文件)的最大大小,必须 ≥upload_max_filesize。如果表单里除了文件还有别的字段,post_max_size要比文件上限更大一些。memory_limit:PHP 进程可用内存,处理大文件时要留出余量,否则会内存不足。
典型配置(在 php.ini 里修改):
upload_max_filesize = 100M
post_max_size = 110M
memory_limit = 256M
max_execution_time = 300
max_input_time = 300
同时别忘了 PHP-FPM 池配置里的超时(/etc/php-fpm.d/www.conf 或 /etc/php/8.1/fpm/pool.d/www.conf):
request_terminate_timeout = 300
改完重启对应服务:
# Debian/Ubuntu(注意版本号)
sudo systemctl restart php8.1-fpm
# RHEL/CentOS/Rocky
sudo systemctl restart php-fpm
一个常见误区:只在 .htaccess 或 ini_set() 里改 upload_max_filesize 是无效的,因为这两个是 PHP_INI_PERDIR 级别,必须在 php.ini、httpd 配置或 .user.ini 里设置才能生效。post_max_size 同理。改错地方却不报错、不生效,特别容易误导排查。
四、第三步:确认后端框架与网关的限制
排除了 Nginx 和 PHP,还剩后端框架和中间网关。不同技术栈的限制点不同:
# Spring Boot(Java)常见请求体限制
# application.yml 或 properties
# spring.servlet.multipart.max-file-size=100MB
# spring.servlet.multipart.max-request-size=100MB
# 老版本用 spring.http.multipart.*
# Node.js(Express + multer)
# multer({ limits: { fileSize: 100 * 1024 * 1024 } })
# 若前面有云 WAF 或 API 网关,也有独立的请求体大小限制
# 需要到对应控制台查看并调整
这类限制在应用日志里通常有更明确的报错,比如 Java 的 MaxUploadSizeExceededException、Node 的 PayloadTooLargeError。看到这类错误就知道是框架层在拦,改框架配置即可。
排查顺序总结成一个原则:从外往里逐层确认。先 Nginx,再 PHP/应用运行时,再框架,最后网关。哪层报错对应哪层配置,避免一次改一堆、出了问题不知道是谁的锅。
前后端分离场景要特别注意
当 Nginx 只做反向代理、后端是自己的应用(Java、Go、Node 等)时,"Nginx 的 client_max_body_size"和"后端的请求体限制"是两道独立的门,必须都放开。常见情况是:把 Nginx 的 client_max_body_size 从 1m 调到 100m 后,413 依旧,因为后端框架自己的上限还是默认值。这时要看后端的报错日志,而不是盯着 Nginx。反过来,如果后端放开了但 Nginx 没放开,请求根本到不了后端,Nginx 直接返回 413,后端日志里连这条请求都看不到。判断方法很简单:如果 Nginx 的 access.log 里有这条请求且状态是 413,多半是 Nginx 拦的;如果后端日志里压根没有这次上传记录,也说明是前面某一层挡住了。理清"请求到底走到了哪一层",比盲目调参高效得多。
用真实文件做验证
改完配置不要只看设置值,要用一个真实文件验证。文件大小建议取"明显超过原限制、又低于新限制"的中间值,比如原来限制 1MB,你调到了 100MB,就用一个 30MB 左右的文件测试。测试时观察是上传成功、还是报 413、或者报其他错误(比如超时或内存不足),据此判断是"限制"问题还是"资源"问题。如果 30MB 能传、80MB 报 413,说明还有一层没放开;如果传到一半断掉,多半是超时或内存问题,要回到第三节调超时和 memory_limit。
五、放宽上传限制的安全风险
把上传限制调大很方便,但也打开了攻击面,需要权衡:
- 磁盘打满风险。放开上传后,攻击者可以反复上传大文件消耗磁盘,导致服务不可用。要配合磁盘配额、上传频率限制和定期清理。
- 大请求拖垮后端。超大请求体会占用内存和连接更久,慢速上传(slowloris 类)还可能耗尽连接数。Nginx 有
client_body_timeout、client_header_timeout可缓解。 - 恶意文件上传。限制放宽后,要更严格地校验文件类型、内容、扩展名,上传目录禁止执行脚本(
location里对上传目录deny执行.php等),并用独立域名或目录隔离。 - 临时文件放大。Nginx 缓冲大请求体会写临时文件,PHP 也会用临时目录,要注意对应分区空间。
给几点落地建议:
# 上传目录禁止解析脚本(安全必备,Nginx 示例)
location ^~ /uploads/ {
location ~ \.(php|php5|phtml|jsp|asp|aspx)$ {
deny all;
}
}
# 限制请求体读取超时,缓解慢速上传
client_body_timeout 60s;
风险提示:这些配置涉及行为改变,改动前建议备份原配置(例如 cp nginx.conf nginx.conf.bak),在低峰期操作,并准备好回滚。
六、一套完整的排查清单
| 步骤 | 检查点 | 命令/位置 |
|---|---|---|
| 1 | Nginx 是否拦 | error.log 的 too large body;client_max_body_size |
| 2 | PHP 上传上限 | upload_max_filesize、post_max_size、memory_limit |
| 3 | PHP-FPM 超时 | request_terminate_timeout |
| 4 | 应用运行时 | Java/Node/Go 各自的请求体限制 |
| 5 | 网关/WAF/CDN | 控制台里的请求体大小设置 |
| 6 | 临时目录空间 | df -h 看 Nginx/PHP 临时目录所在分区 |
| 7 | 安全加固 | 上传目录禁执行脚本、限制频率 |
改完每一层都要 nginx -t(Nginx)或重启对应服务(PHP/框架),并用一个刚好超过原限制、又低于新限制的文件做实际测试,确认生效。
常见问题
Q:Nginx 的 client_max_body_size 已经改成 100m,为什么还 413?
看 413 是不是其他层返回的。可能 PHP 的 post_max_size 太小,或框架自己有上限,也可能前面 CDN/WAF 拦的。逐层确认。
Q:post_max_size 和 upload_max_filesize 谁大谁小?
post_max_size 要 ≥ upload_max_filesize。因为整个 POST 请求还包含其他字段,通常建议 post_max_size 比文件上限大 10%-20%,留出余量。
Q:.htaccess 里改 upload_max_filesize 没用?
对,这两个参数是 PHP_INI_PERDIR 级别,只能改 php.ini、httpd 配置或 .user.ini(需 user_ini.filename 生效),.htaccess 和 ini_set() 里改无效。
Q:调大限制后出现超时?
上传大文件耗时长,要同步调大 max_execution_time、max_input_time、request_terminate_timeout 和 Nginx 的 client_body_timeout,几处超时要协调一致。
Q:413 会影响搜索引擎吗?
一般不影响爬虫抓取普通页面,但如果站点关键内容以 413 返回,会导致该页面抓取失败。同时,开放大文件上传要防被滥用作消耗带宽和磁盘的入口。
总结
413 表示请求体超过限制,限制可能藏在 CDN/WAF、Nginx、PHP、后端框架等多层,需要从外往里逐层确认。
Nginx 的 client_max_body_size 默认 1MB 是高频坑点,按需要在 location 粒度放开更安全;nginx -t 通过后再 reload。
PHP 侧要同时调 upload_max_filesize、post_max_size、memory_limit,并注意它们必须在 php.ini/.user.ini 里改,.htaccess 和 ini_set() 无效;post_max_size 要大于文件上限。
放宽限制会带来磁盘打满、慢速上传、恶意文件上传等风险,务必给上传目录禁止执行脚本、限制频率并做好清理。
改动涉及配置行为,操作前备份、低峰期执行、准备好回滚,并用实际大文件测试确认每一层都生效。
企业QQ咨询




