大文件上传失败主因是php底层限制而非laravel,需同步调整php.ini中upload_max_filesize、post_max_size、max_execution_time、max_input_time,并配置nginx的client_max_body_size;同时确保上传临时目录可写、磁盘空间充足;分片上传需前后端协作实现,用文件级hash(如sha256)支持秒传与断点续传,每片须单独校验md5防损坏。

大文件上传直接失败,php.ini 限制是第一道坎
不是 Laravel 框架的问题,而是 PHP 底层拦住了。上传超限会直接返回 413 Request Entity Too Large 或静默截断,连 Laravel 的入口都进不去。
必须同步调低三处阈值:
-
upload_max_filesize(单文件上限,如200M) -
post_max_size(整个 POST 请求体上限,需 ≥upload_max_filesize) -
max_execution_time和max_input_time(避免超时中断,尤其网络慢时)
改完记得重启 PHP-FPM 或 Apache。Nginx 还要额外加 client_max_body_size 200M;,否则它会在 PHP 前就拒掉请求。
request()->file() 拿不到大文件?检查临时目录和权限
即使 php.ini 改了,PHP 仍可能因临时目录不可写而丢弃上传文件,此时 request()->file('video') 返回 null,且无明显报错。
验证方式很简单:
- 打印
ini_get('upload_tmp_dir')看路径 - 用
is_writable()检查该目录是否可写 - 确认磁盘空间足够(
df -h)
常见坑:Docker 容器里挂载的临时目录没给 www-data 写权限;或者 SELinux 启用后阻止了写入。
分片上传不是 Laravel 自带能力,得自己搭前后端协作流程
Laravel 不提供分片上传内置支持,所谓「Laravel 分片上传」其实是你控制前端切片 + 后端拼接,框架只负责收、存、校验。
关键设计点:
- 前端按固定大小(如
5MB)切片,每片带唯一identifier(如文件 hash)、filename、chunkIndex、totalChunks - 后端用
Storage::put()把每片存到临时位置(如chunks/{identifier}/{index}) - 收到最后一片时,用
Storage::readStream()逐个读片、fopen('php://output', 'w')拼接,再Storage::put()写成完整文件
别用 file_put_contents 直接拼 —— 大文件易爆内存;也别在数据库里存所有分片路径再查 —— 高并发下容易漏片或重复提交。
分片续传和秒传依赖客户端 hash,Hash::make() 不适用
Hash::make() 是为密码设计的慢哈希,不能用于文件内容校验。秒传和断点续传必须用 md5_file() 或前端 Web API 的 FileReader + crypto.subtle.digest() 算出文件级 hash(如 md5 或 sha256)。
后端收到 hash 后,先查 storage/app/finished/{hash} 是否已存在,存在就跳过上传直接返回成功。注意:md5 碰撞概率虽低,但视频类大文件建议至少用 sha256,尤其是多用户共用系统时。
真实项目里最容易被忽略的是:前端没做分片 hash 校验,导致某一片传坏却没发现,最后拼出来的是损坏视频 —— 必须让每片也带自己的 md5,后端收到后立即校验再落盘。










