413错误是Nginx在请求抵达PHP前拦截所致,需检查并设置client_max_body_size(单位M/G,不可写MB),同步调大upload_max_filesize和post_max_size,重启php-fpm并用phpinfo()确认生效。

413 错误根本没进 PHP,先查 Nginx 的 client_max_body_size
返回 413 就说明请求在抵达 PHP 前就被 Nginx 拦截了,PHP 根本没机会解析 $_FILES 或报 UPLOAD_ERR_INI_SIZE。这时候改 php.ini 没用,日志里也找不到 PHP 错误。
检查点:
-
nginx -t确认配置语法无误 - 在对应站点的
server块(不是http全局块)里加:client_max_body_size 50M; - 别写成
client_max_body_size 50MB—— 单位只认M、G,B会被忽略,变成 50 字节 - 如果用了云负载均衡(如阿里云 SLB),它也有独立 body size 限制,需同步调大
upload_max_filesize 和 post_max_size 必须配对改,且后者要更大
ThinkPHP 5.1 不会绕过 PHP 底层校验,upload_max_filesize 控单文件,post_max_size 控整个 POST 请求体(含所有字段 + 文件二进制流)。哪怕只传一个文件,只要 POST 总体积超了 post_max_size,也会被截断,报错是 UPLOAD_ERR_FORM_SIZE(值为 2)或静默丢数据。
实操建议:
立即学习“PHP免费学习笔记(深入)”;
- 设
upload_max_filesize = 50M,则post_max_size至少得52M(留 2MB 给表单字段和 header) - 单位必须用
M,不能带引号、空格或MB - 改完后必须重启
php-fpm(不是只 reload nginx),并用phpinfo()页面确认“Loaded Configuration File”路径下的值已更新 - 别忽略
max_execution_time = 300和memory_limit = 256M,大文件上传+验证容易超时或爆内存
TP5.1 控制器里 $file->validate() 的 size 是字节,不是 M
框架层校验是 PHP 接收成功后的第二道关,不触发 413,但会返回 “上传文件过大” 这类业务提示。它的 size 参数单位是字节,和 php.ini 完全无关。
常见错误写法:
-
['size' => '50M']→ 字符串无效,校验直接跳过 -
['size' => 50]→ 50 字节,显然太小 -
['size' => 52428800]✅ 正确(50 * 1024 * 1024)
典型用法:
$file = $this->request->file('avatar');
$rule = ['size' => 52428800, 'ext' => ['jpg', 'png']];
if (!$file->validate($rule)) {
$this->error($file->getError());
}
上传失败却没报错?检查 upload_tmp_dir 权限和磁盘空间
报 File upload error – unable to create a temporary file(错误码 UPLOAD_ERR_NO_TMP_DIR 或 UPLOAD_ERR_CANT_WRITE)跟大小限制完全无关,90% 是临时目录问题。
排查步骤:
- 运行
var_dump(ini_get('upload_tmp_dir')),看实际生效路径 - 确认该目录存在,且 Web 进程用户(如
www-data或nginx)有读写权限 - 执行
df -h /tmp查剩余空间;若用自定义目录(如/var/tmp/php-uploads),同样查该分区 - SELinux 或 AppArmor 启用时,可能拦截写入,临时禁用测试:
setenforce 0
最易被忽略的是:Nginx + PHP-FPM 环境下,upload_tmp_dir 的权限归属必须同时满足 Nginx worker 进程和 PHP-FPM 子进程的 uid/gid,否则一个能写、一个不能写,上传就卡在临时文件阶段。



















