必须同步调整php、nginx、php-fpm三层超时配置,否则任一环节超时会导致504、空白页或$_files为空;真正稳定方案是前端分片上传+后端流式合并。

PHP处理大文件上传时超时,不是改一个max_execution_time就能解决的——它本质是请求接收、临时存储、脚本执行三个阶段被不同层级分别掐断的结果。必须同步调 PHP、Web 服务器(Nginx)、PHP-FPM 三层配置,否则任一环节卡住都会返回 504、空白页或$_FILES为空。
为什么改了max_execution_time还是超时?
因为上传流程分三段,每段有独立超时控制:
-
max_input_time:PHP 解析整个 POST 请求体(含文件流)的最长时间。若网络慢或 Nginx 传得慢,它可能先于max_execution_time触发中断,且错误静默($_FILES['error']仍为 0) -
client_body_timeout(Nginx):从客户端开始发数据起,Nginx 等待完整 body 到达的最长时间。设太小(默认 60s),上传中途卡顿几秒就直接断连 -
request_terminate_timeout(PHP-FPM):FPM 进程自身强制 kill 超长请求的开关。即使 PHP 和 Nginx 都放行,FPM 仍会单方面终止
Nginx 层最容易漏掉的两个 timeout
很多只改 PHP 配置的人,在 Nginx 里只加了client_max_body_size,却忘了这两个关键项:
-
client_body_timeout 600:加在server或location ~ \.php$块内,单位秒,防慢速上传中断 -
fastcgi_read_timeout 600:必须 ≥ PHP 的max_execution_time,否则 Nginx 在等 PHP-FPM 响应时主动关闭连接,报 504 - 如果用了
proxy_pass(比如转发到另一个服务),还要加proxy_read_timeout 600 - Cloudflare 免费版硬限 100 秒,无法绕过;必须升级或让大文件上传路径绕过 CDN
PHP 层必须四参数同调
单独调大upload_max_filesize毫无意义,这四个值要成套改:
-
upload_max_filesize = 512M:单个文件上限 -
post_max_size = 520M:必须 ≥ upload_max_filesize + 表单其他字段开销,否则整个 POST 被截断($_POST和$_FILES全空) -
max_input_time = 600:常被忽略,但它是接收文件流的“第一道门” -
max_execution_time = 600:含move_uploaded_file()、校验、压缩等后续操作 -
memory_limit = 1G:建议 ≥ 1.5 ×post_max_size,否则move_uploaded_file()可能因缓冲区不足失败
改完确认生效的php.ini路径(用phpinfo()查Loaded Configuration File),然后必须sudo systemctl restart php7.4-fpm和sudo systemctl reload nginx,reload对 PHP-FPM 无效。
真正稳定的方案其实是绕开超时
硬调 timeout 和 size 是权宜之计。超过 2GB 时,PHP 的$_SERVER['CONTENT_LENGTH']可能因 32 位整数溢出导致计算错误;磁盘 I/O 慢、NFS 挂载、临时目录被自动清理,都会让move_uploaded_file()静默失败。
生产环境推荐分片上传:
- 前端用
File.slice()切块(如每块 5MB),每个请求带chunk_index、total_chunks、file_id - 后端接收后存为
/tmp/uploads/{file_id}/{index}.part,不走$_FILES临时机制 - 合并时用
fopen('ab')流式追加,避免把整个文件读进内存 - 配合 Redis 记录已上传块,实现断点续传
这不是“更复杂”,而是把不可控的单次长请求,拆成多个可控的短请求——超时风险、内存压力、网络容错能力全部改善。配置调参只是兜底,分片才是正解。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











