上传一个 20MB 的图片、数据库备份包或者 WordPress 主题,页面突然报:
413 Request Entity Too Large
这个错误很常见,尤其是刚迁移到 VPS、刚装完 Nginx + PHP-FPM、或者前面套了 Cloudflare 的网站。
它的意思不是“文件坏了”,也不是“硬盘满了”,而是某一层服务觉得你这次请求太大,直接拒收。
最常见的层级有四个:
- Nginx 的
client_max_body_size; - PHP 的
upload_max_filesize和post_max_size; - 应用自己的上传限制,比如 WordPress、Laravel、宝塔面板;
- CDN / 反向代理的限制,比如 Cloudflare。
排查 413 的关键是:不要只改一个地方。最低的那个限制会生效。
先用浏览器开发者工具看响应头,或者直接 curl:
curl -I https://example.com/upload
如果响应里有:
Server: nginx
大概率是 Nginx 先挡住了。
如果你套了 Cloudflare,响应头可能看到:
server: cloudflare
cf-ray: xxxxx
这时要分清是 Cloudflare 拒绝,还是 Cloudflare 转发后源站拒绝。
再看 Nginx 日志:
sudo tail -n 80 /var/log/nginx/error.log
典型日志是:
client intended to send too large body: 20971520 bytes
看到这句,方向就很明确:Nginx 的请求体大小限制太小。
Nginx 默认限制通常很小,很多环境是 1MB。上传图片都可能不够。
打开站点配置:
sudo nano /etc/nginx/sites-available/example.com
或者你的配置在:
/etc/nginx/conf.d/example.conf
在 server 块里加:
server {
server_name example.com;
client_max_body_size 100M;
root /var/www/example.com;
index index.php index.html;
}
如果只想对某个上传接口放大限制,也可以放到 location 里:
location /upload/ {
client_max_body_size 100M;
try_files $uri $uri/ /index.php?$query_string;
}
不建议直接写 0 取消限制。上传口完全不限制,遇到恶意请求很容易把磁盘、内存或临时目录打满。
改完先测试:
sudo nginx -t
没问题再 reload:
sudo systemctl reload nginx
如果你用的是 OpenResty、宝塔 Nginx、Nginx Proxy Manager,本质也是找 client_max_body_size,只是配置入口不同。
很多人只改 Nginx,结果 413 没了,但上传页面又提示文件太大。这是因为请求终于到了 PHP,PHP 自己又拦了一次。
先找 PHP 配置文件:
php --ini
如果你跑的是 PHP-FPM,不同版本可能在:
/etc/php/8.2/fpm/php.ini
/etc/php/8.1/fpm/php.ini
/etc/php/7.4/fpm/php.ini
改这几个值:
upload_max_filesize = 100M
post_max_size = 100M
max_execution_time = 300
max_input_time = 300
memory_limit = 256M
注意:post_max_size 要大于或等于 upload_max_filesize。
如果你要上传 100MB 文件,我一般会这样配:
upload_max_filesize = 100M
post_max_size = 120M
memory_limit = 256M
改完重启 PHP-FPM:
sudo systemctl restart php8.2-fpm
版本号按你的机器改。可以查看:
systemctl list-units | grep php | grep fpm
WordPress 用户最容易卡在这里。
Nginx 和 PHP 都改了,但后台媒体库还是显示最大上传 2MB、8MB、32MB,这说明 PHP-FPM 没读到你改的配置,或者还有面板/插件在限制。
可以在站点目录临时放一个 phpinfo.php:
<?php phpinfo();
访问后搜索:
upload_max_filesize
post_max_size
Loaded Configuration File
确认页面显示的是新值。
看完记得删掉:
rm /var/www/example.com/phpinfo.php
WordPress 还要检查:
- 安全插件是否限制上传;
- 主题或插件是否自己限制文件大小;
wp-config.php里有没有相关配置;- 宝塔面板里 PHP 配置是否覆盖了手动改动。
不要只看命令行 php --ini,Web 站点实际用的是 PHP-FPM,两个配置文件可能不是同一个。
如果你的架构是:
用户 -> Nginx 反向代理 -> Docker / Node / PHP / 后端服务
那前面的 Nginx 要放大限制,后面的服务也要放大。
比如 Nginx 反代到 Node:
location /api/ {
client_max_body_size 100M;
proxy_pass http://127.0.0.1:3000;
}
Express 里也可能有 body limit:
app.use(express.json({ limit: '100mb' }));
app.use(express.urlencoded({ limit: '100mb', extended: true }));
Laravel / Symfony / Django / Rails 也各有自己的上传限制。Nginx 放行不代表应用一定接受。
所以如果 Nginx 日志没有 413,但应用日志有上传错误,就去查应用层。
如果网站前面套了 Cloudflare,别忘了它也有限制。
Cloudflare 不同套餐的上传大小上限不一样。免费版和低套餐通常不适合直接上传超大文件。
如果你要传几百 MB 的备份包,最好不要走普通网页上传。更稳的方式是:
- 用 SFTP / SCP 上传到 VPS;
- 用对象存储直传;
- 后台上传改成分片上传;
- 临时暂停代理,灰云直连源站测试。
测试时可以把 DNS 记录从橙云改成灰云,绕过 Cloudflare,再看 413 是否消失。
如果绕过后正常,就不是 VPS 的 Nginx 或 PHP 问题,而是 CDN 层限制。
很多人用 Docker 跑 WordPress、Nextcloud、Laravel,结果在宿主机改 /etc/nginx,完全没用。
先确认 Nginx 在哪里:
docker ps
如果 Nginx 在容器里,配置也在容器里,或者通过 volume 挂载出来。
常见路径:
/etc/nginx/conf.d/default.conf
/etc/nginx/nginx.conf
改完要 reload 容器里的 Nginx,或者重启容器:
docker exec -it nginx nginx -t
docker exec -it nginx nginx -s reload
如果用 docker compose:
docker compose restart nginx
Nextcloud 还要看 PHP 和应用自己的配置。只改反代层,经常不够。
如果你只是偶尔上传 50MB 图片,改到 100M 问题不大。
但如果你经常传 1GB、5GB 的备份包,不建议单纯把限制拉很大。原因很简单:
- 上传中断后容易重来;
- Nginx 临时文件可能占满磁盘;
- PHP 处理大文件容易超时;
- 反向代理链路越长,失败点越多;
- 恶意请求更容易打满带宽和磁盘。
这类场景更适合:
scp backup.tar.gz root@server:/data/backups/
或者用 rsync:
rsync -avP backup.tar.gz root@server:/data/backups/
如果是网站后台给用户上传大文件,建议做分片上传或对象存储直传,不要让所有大文件都穿过 PHP。
| 现象 | 最可能原因 | 先查什么 |
|---|---|---|
| 页面直接显示 413 | Nginx 请求体限制 | client_max_body_size、Nginx error.log |
| 413 消失但应用提示文件太大 | PHP 限制 | upload_max_filesize、post_max_size |
| WordPress 后台仍显示 2MB | PHP-FPM 没读到配置 | phpinfo()、FPM 版本、面板配置 |
| 只有 API 上传失败 | 反代或应用限制 | Nginx location、应用 body limit |
| 绕过 Cloudflare 后正常 | CDN 上传限制 | Cloudflare 套餐限制、灰云测试 |
| Docker 改宿主机无效 | 配置在容器内 | docker ps、容器 Nginx/PHP 配置 |
遇到 413,我一般按这个顺序:
sudo tail -n 80 /var/log/nginx/error.log
sudo nginx -T | grep -n client_max_body_size
sudo nginx -t
确认 Nginx 后,再看 PHP:
php --ini
systemctl list-units | grep php | grep fpm
如果是 WordPress,就用 phpinfo() 确认 Web 环境真实读取的值。
如果前面有 Cloudflare,就再做一次灰云直连测试。
普通网站上传图片、主题、插件,通常这样够用:
Nginx:
client_max_body_size 100M;
PHP:
upload_max_filesize = 100M
post_max_size = 120M
max_execution_time = 300
max_input_time = 300
memory_limit = 256M
如果你只需要上传 20MB 文件,不要直接改到 1GB。限制不是越大越好,够用就行。
413 的本质是“请求体太大”,但真正麻烦的是链路上每一层都有自己的上限。按 Nginx、PHP、应用、CDN、Docker 这个顺序查,基本不会跑偏。
