php上传大文件报413错误是nginx在请求进入php前拦截所致,需同步调整nginx的client_max_body_size(须≥post_max_size)、php的upload_max_filesize和post_max_size(后者≥前者)、memory_limit(≥1.5倍post_max_size)及超时参数,并重载服务生效。

PHP 8.2 网站上传文件时提示“超出大小限制”或直接返回空 $_FILES、413 错误、页面空白,说明上传流程在抵达 PHP 处理逻辑前就被某一层拦截了——这通常不是代码写错了,而是 upload_max_filesize、post_max_size、Nginx client_max_body_size 三者未对齐,或 memory_limit 不足导致解析失败。
确认当前生效的配置值
新建一个 check.php 文件,内容为:
访问该页面,搜索 “Loaded Configuration File”,记下实际加载的 php.ini 路径;再分别查找 upload_max_filesize、post_max_size、memory_limit、max_execution_time 四项的 Local Value 和 Master Value。若 Local Value 显示为 “no value”,说明该配置未被当前上下文加载,可能被覆盖或禁用。
【必须确认 Loaded Configuration File 是你正在编辑的那个文件】 否则所有修改都无效。
修改 php.ini 中核心三项参数
用文本编辑器以管理员权限打开上一步确认的 php.ini 文件。
找到 upload_max_filesize 行,取消注释(删除开头分号),改为期望值,例如:
upload_max_filesize = 256M
找到 post_max_size 行,设为 ≥ upload_max_filesize 的值,建议预留 8–16M 缓冲,例如:
post_max_size = 272M
找到 memory_limit 行,设为至少 1.5 倍 post_max_size,且不低于 256M,例如:
memory_limit = 512M
顺手检查 max_execution_time 和 max_input_time,大文件上传需更长时间,建议统一设为 600:
max_execution_time = 600
max_input_time = 600
同步调整 Nginx 的 client_max_body_size
仅改 PHP 配置没用。Nginx 在请求进入 PHP 前就会拦截整个 multipart 请求体。若 client_max_body_size 小于 post_max_size,请求根本不会到达 PHP。
打开 Nginx 站点配置文件(通常在 /etc/nginx/sites-enabled/your-site 或 /usr/local/nginx/conf/nginx.conf),在 server 块内添加:
client_max_body_size 256M;
如果该站点使用 proxy_pass 转发到 PHP-FPM,还需在 location ~ \.php$ 块中加:
proxy_read_timeout 600;
执行 sudo nginx -t 验证语法,再运行 sudo systemctl reload nginx 生效。
验证并排除常见陷阱
方法一:用 check_upload.php 快速验证
新建 check_upload.php,内容为:
echo 'upload_max_filesize: ' . ini_get('upload_max_filesize') . "
\n";
echo 'post_max_size: ' . ini_get('post_max_size') . "
\n";
echo 'memory_limit: ' . ini_get('memory_limit') . "
\n";
echo 'max_execution_time: ' . ini_get('max_execution_time');
?>
访问该文件,确认输出值与 php.ini 中一致。
方法二:检查错误日志定位真实卡点
查看 PHP 错误日志路径(phpinfo() 页面中 error_log 项),打开日志文件,搜索关键词 “POST Content-Length” 或 “request entity too large”。前者说明 post_max_size 不够,后者说明 Nginx 的 client_max_body_size 拦截了请求。
方法三:临时关闭安全模块排查
若使用 ModSecurity(Apache)或某些 WAF 插件,它们可能独立限制 POST 大小。可临时在 Apache 配置中加入 SecRequestBodyLimit 0 关闭限制测试,确认是否为中间件干扰。
PHP 8.2 特别注意:上传后内存不释放
上传一个 200MB 文件后,脚本结束但 memory_get_usage(true) 仍居高不下?这不是 bug,是 PHP 8.2 的内存管理机制特性:Zend MM 不会立即将大块内存归还 OS。
确保你没有用 file_get_contents($_FILES['file']['tmp_name']) 把整个文件读进变量;若已读取,必须显式 unset($content) 或 $content = null。
推荐流式处理:用 fopen($_FILES['file']['tmp_name'], 'rb') → fread($fp, 8192) 分块读取 → 每次处理完立即 unset($buffer) → 处理完毕 fclose($fp)。
【move_uploaded_file() 只移动文件,不释放内存;真正占用内存的是你手动读取的内容】
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











