发布时间:2026-09-14 08:17 更新时间:2026-09-14 08:17 阅读量:0
后台想传一个几百兆的备份包、一段产品视频,进度条走到一大半突然弹个 413,或者页面转完圈回到空白,目标目录里空空如也。这类问题十有八九不是程序写错了,而是请求体在进入站点的路上被三道闸门依次拦下:Nginx 的 client_max_body_size、PHP 的 post_max_size 和 upload_max_filesize。它们各有各的默认值,只改一处往往还是失败,下面把顺序和写法一次讲透。
浏览器发出的上传请求,最先抵达的是 Nginx(或者你前面的反代、CDN)。Nginx 用 client_max_body_size 判断整个请求体的大小,一旦超出,请求根本不会转发给 PHP,直接返回 413 Request Entity Too Large。这个值默认是 1m,所以很多站点一上来就卡在这一层。
Nginx 放行之后,请求体交给 PHP-FPM 处理。PHP 先看 post_max_size,它限制的是整个 POST 请求体,包括表单里的普通字段和文件内容。超出之后 PHP 不会抛出一个漂亮的报错,而是把 $_POST 和 $_FILES 清空,脚本里表现成「什么都没收到」,这也是最容易被误判成程序 bug 的一种情况,post_max_size 默认是 8M。
再往里一层才是 upload_max_filesize,它只针对单个上传文件的体积,默认 2M。超过它时文件条目还在 $_FILES 里,但 error 值会变成 UPLOAD_ERR_INI_SIZE,也就是数字 1。
所以三者的关系要满足:client_max_body_size 大于等于 post_max_size,post_max_size 大于 upload_max_filesize,中间一般留 1~2MB 的余量给表单其他字段。另外还要顺带关注 memory_limit、max_input_time、max_execution_time,它们不直接决定体积,但会在处理大文件或慢速上传时拖后腿,具体行为以 PHP 官方文档和你实际环境为准。
第一步是确认真正生效的 php.ini 是哪一个,改错文件是新手最常见的翻车点。命令行可以这样查:
php -i | grep -E "Loaded Configuration File|upload_max_filesize|post_max_size|memory_limit|max_input_time|upload_tmp_dir"如果你用的是 PHP-FPM,命令行读到的值和网站实际生效的值有可能不一致,更稳妥的做法是让站点输出一个 phpinfo() 页面看一眼,或者在宝塔等面板的 PHP 设置里核对,一切以实际生效值为准。找到文件后在 [PHP] 段调整:
upload_max_filesize = 512M
post_max_size = 520M
memory_limit = 512M
max_execution_time = 300
max_input_time = 300
upload_tmp_dir = /tmp这里 memory_limit 建议不低于 post_max_size,否则处理图片时容易因内存不足中断。upload_tmp_dir 指向的分区要有足够剩余空间,大文件在接收阶段是先落到临时目录的。改完必须重载对应的 PHP-FPM 服务,版本号按你的实际环境替换:
systemctl reload php8.2-fpm第三步轮到 Nginx。client_max_body_size 可以写在 http、server 或 location 任意一层,就近生效:
client_max_body_size 520m;
client_body_buffer_size 1m;
client_body_temp_path /var/cache/nginx/client_temp;
fastcgi_read_timeout 300s;超出 client_body_buffer_size 的部分会被写成临时文件,所以 client_body_temp_path 所在磁盘同样要留出空间。如果你前面还挂了一层 Nginx 反向代理,反代那一层的 client_max_body_size 也要一并放行,否则照样 413。改完先校验再重载:
nginx -t && systemctl reload nginx如果日志里能看到 413 或者 client intended to send too large body 这样的字样,说明还没绕过 Nginx 那一关,回头检查是不是改错了 server 块,或者配置被其他 include 的文件覆盖了。如果 Nginx 已经不报错,但文件还是没落地,就去看 PHP 的错误日志和 $_FILES 里的 error 值,确认到底是体积超限还是超时中断。
别忘了外层还有变量:CDN、云 WAF、负载均衡通常也有各自的请求体上限,各家数值不一样,需要查对应厂商的官方文档。用 WordPress 的话,后台媒体库还会读取 PHP 的限制,插件里设置的值不能超过 PHP 实际允许的上限,否则只是自我安慰。最后做个验证:拿一个接近上限的文件实际传一次,同时开着 nginx 错误日志和 PHP 错误日志观察。
如果站点经常要传几百 MB 以上的素材,与其反复抬高这些参数,不如把大文件走对象存储的直传方案,由前端拿签名直接传到 OSS、COS 之类的服务,再把地址写回数据库。这样既不用把 PHP 的超时和内存一路放大,也能减少服务器带宽占用。参数调整解决的是「能不能传」,架构调整解决的才是「传得稳不稳」。
| 📑 | 📅 |
|---|---|
| phpMyAdmin导入大SQL超时:参数调整与命令行导入 | 2026-09-12 |
| HTTPS证书有效却提示不安全:混合内容的定位与批量修复 | 2026-09-12 |
| 服务器磁盘被写满的排查流程:df与du定位、日志切割与清理注意事项 | 2026-09-11 |
| 宝塔面板安全加固:面板端口、安全入口、SSL与登录告警设置 | 2026-09-11 |
| Nginx 502/504 排查:从错误日志到PHP-FPM进程池状态 | 2026-09-10 |
| Nginx反向代理缓存实战:proxy_cache_path配置与命中率排查 | 2026-09-15 |
| Let's Encrypt证书自动续期失败排查:certbot renew定时任务与webroot验证 | 2026-09-15 |
| WordPress数据库膨胀排查:wp_options自动加载与孤立表清理 | 2026-09-15 |
| 宝塔面板计划任务做网站自动备份:数据库与文件打包、异地存储配置 | 2026-09-15 |
| CDN回源配置怎么填:回源Host、回源协议与真实IP排查 | 2026-09-16 |