现场是这样的。客户要在后台传 2G 的素材包,PHP 7.4 环境,nginx 的 client_max_body_size 已经改成 4096m,上传到 100% 后页面提示 POST Content-Length of 2147483648 bytes exceeds the limit of 8388608 bytes。
中间走过弯路,把「memory_limit 不够,文件读进内存时直接失败」当成主因,改完现象没变。
把日志和配置对完,能解释这个现象的基本就这几处。php.ini 的 upload_max_filesize 还是默认的 2M;post_max_size 比 upload_max_filesize 小,请求在进入脚本前就被丢掉;max_input_time 和 max_execution_time 太短,大文件传到一半被切断。
第一件事是列出三个相关参数的实际值
php -i | grep -E 'upload_max_filesize|post_max_size|memory_limit'
然后在 php.ini 里统一改到足够大
sed -i 's/^upload_max_filesize.*/upload_max_filesize = 2048M/;s/^post_max_size.*/post_max_size = 2048M/' /etc/php.ini
接着放宽执行时间并重启 fpm
systemctl restart php-fpm
末了用 curl 模拟一次真实上传
curl -F 'file=@/data/test2g.bin' -o /dev/null -w '%{http_code}' http://127.0.0.1/upload.php
同一份数据我导出了两份,一份留底,一份拿来试。
这类问题以前遇到过,但这次的触发条件和上次不一样。
恢复的判定其实很直接。上传进度到 100% 后返回 200 且文件落盘大小一致,PHP 错误日志里不再有 POST Content-Length 的提示。
提醒一点。post_max_size 不能小于 upload_max_filesize,再叠加 nginx 的 client_max_body_size 要一起改;超大文件建议直接走分片或直传对象存储。拖得越久,排查成本越高,因为现场状态会被后续操作覆盖。
