PHP上传大文件需同步调大post_max_size和upload_max_filesize,且Nginx的client_max_body_size必须同步配置,否则请求在到达PHP前就被拦截;超时设置(fastcgi_read_timeout、max_execution_time等)也需延长。

PHP 的 post_max_size 和 upload_max_filesize 必须同时调大
ThinkPHP 上传大文件失败,报 Post size exceeded,本质是 PHP 拦截了超限的 POST 数据,不是框架问题。关键在两个 ini 配置:前者限制整个 POST 请求体大小(含所有字段+文件),后者只管单个上传文件。很多人只改了 upload_max_filesize,忘了 post_max_size 必须 ≥ 它,否则文件还没进到上传逻辑就被 PHP 直接拒掉。
实操建议:
-
post_max_size建议设为略大于最大预期上传总大小(比如多文件 + 表单字段合计 100MB,则设128M) -
upload_max_filesize设为单文件上限(如64M) - 修改后必须重启 PHP-FPM(
systemctl restart php-fpm或对应版本命令),仅 reload 不生效 - 用
phpinfo()页面确认值已更新,别只信配置文件写对了
Nginx 的 client_max_body_size 是第一道关卡
即使 PHP 配置全放开,Nginx 默认只允许 1MB 的请求体,超了直接返回 413 Request Entity Too Large,根本不会把请求转给 PHP。这个配置必须显式增大,且要放在 server 或 location 块里,不能只写在 http 块(除非你确定所有接口都需大上传)。
常见错误现象:
- 浏览器控制台看到 413 错误,但 PHP 错误日志空空如也 → 八成是 Nginx 拦截了
- ThinkPHP 日志里没记录上传动作,
$_FILES为空 → 请求压根没到 PHP 层
实操建议:
- 在对应站点的
server块中加:client_max_body_size 128m; - 如果用了反向代理或负载均衡,检查上游网关(如 ALB、SLB)是否也有 body size 限制
- 改完必须
nginx -t && nginx -s reload,语法错会导致 reload 失败但不报错
ThinkPHP 自身的上传验证只是“锦上添花”,不是“救命稻草”
框架层的 validate(['size' => 1024 * 1024 * 64]) 或 maxSize 参数,只在 PHP 成功接收并解析上传后才执行。它拦不住 Post size exceeded 这类底层拦截,更无法绕过 Nginx 413。所以别指望靠改框架配置解决这个问题。
使用场景提醒:
- 适合做二次校验(比如用户传了 10 个 50MB 文件,PHP 接收成功,但业务只要单个 ≤ 64MB)
- 配合
ext验证能防恶意扩展名,但和大小限制无关 - 若开启
think\facade\Filesystem的分片上传,需额外处理断点续传逻辑,此时 Nginx 和 PHP 的超时设置(fastcgi_read_timeout、max_execution_time)也得同步调大
上传超时和连接中断容易被忽略
大文件上传耗时长,Nginx 的 fastcgi_read_timeout(默认 60 秒)、PHP 的 max_execution_time(默认 30 秒)、甚至浏览器自身都有读取超时,任何一个环节先断开,都会导致上传中断且错误信息模糊(比如显示“网络错误”或空响应)。
实操建议:
- 在 Nginx 的 fastcgi_pass 所在 location 块中加:
fastcgi_read_timeout 600;(10 分钟) - PHP 中临时加大超时:
set_time_limit(600);(放在上传入口逻辑开头) - 检查
request_terminate_timeout(PHP-FPM 配置项),它会强制杀死慢请求,优先级高于set_time_limit - 上传过程中别刷新页面或切 Tab,部分浏览器会主动中断 pending 请求
真正麻烦的是多层中间件叠加超时——Nginx、PHP-FPM、PHP 脚本、ThinkPHP 生命周期钩子,每一层都可能掐断,得挨个查日志定位断在哪。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!










