必须同步调大upload_max_filesize、post_max_size和max_execution_time三项参数,分别设为512M、600M和300,否则50MB以上视频上传将因UPLOAD_ERR_INI_SIZE或413错误失败。

PHP接收大视频必须调大哪些php.ini参数
不改配置,50MB以上的视频上传会直接失败,报错 UPLOAD_ERR_INI_SIZE 或 413 Request Entity Too Large。关键三项必须同步调整:
-
upload_max_filesize:设为512M(不能带空格,写成512 M会无效) -
post_max_size:至少比 upload_max_filesize 大 100M,建议设为600M -
max_execution_time:上传+校验阶段可能耗时,设为300(5分钟),避免超时中断
注意:ini_set() 在部分共享主机或 PHP-FPM 模式下被禁用,优先改 php.ini;若只能动态设置,请在入口文件最开头执行,且确认 disable_functions 未禁用 ini_set。
分片上传不是可选项,是必须项
单次 HTTP 上传 >200MB 视频,在弱网、移动端或代理环境下极易中断,且无法续传。ThinkPHP6 或原生 PHP 都不自带分片逻辑,必须前端配合:
- 前端用
WebUploader或qiniu-js-sdk实现分块切片(如每片 5MB) - 后端接收时不做完整文件拼接,而是存为临时分片:
runtime/upload/chunks/{upload_id}/{index} - 所有分片上传完成后,再用
file_put_contents()+FILE_APPEND合并,最后用finfo_open()校验真实 MIME 类型
跳过分片直接走 $_FILES,等于把上传可靠性交给运气——用户传到 99% 断网,就得重来。
立即学习“PHP免费学习笔记(深入)”;
转码绝不能在 Web 请求里同步执行
执行一条 ffmpeg -i input.mp4 ... output.mp4 命令,动辄几十秒,PHP 默认 30 秒超时,exec() 会直接被 kill,返回码 127 或 -1。正确做法是移交控制权:
- 上传成功后只写数据库,状态设为
'uploaded',字段含原始路径、大小、MD5 - 用
think-queue(TP6)或自建 Redis 队列推任务:{"video_id": 123, "preset": "medium", "formats": ["720p", "360p", "webm"]} - Worker 进程独立运行,调用
proc_open()启动 FFmpeg,并捕获 stderr 实时记录进度(避免 exec 被静默截断)
别信“加个 set_time_limit(0) 就能扛住”的说法——PHP 进程卡死会导致整个 FPM worker 挂起,影响其他请求。
存储路径和播放权限必须隔离
视频文件不能放 public/ 目录下直连,否则任意人拼出 URL 就能下载。安全路径结构应类似:
- 原始文件存:
runtime/videos/raw/{user_id}/202609/{md5}.mp4 - 转码后多版本存:
storage/videos/{video_id}/720p.mp4、/cover.jpg、/hls/master.m3u8 - 播放走代理接口:
/video/play?id=123&token=xxx,里面做登录态校验 + 权限判断 +Range头支持
最容易被忽略的是 Content-Range 响应头拼写错误(比如写成 Content-Rangee)或没返回 206 Partial Content 状态码——这会导致 iOS Safari 和部分安卓浏览器无法拖动进度条。



















