要让Laravel稳定接收500MB视频或2GB图纸,需同步调整PHP、Nginx、Laravel三层配置:修改php.ini的upload_max_filesize等四参数并重启php-fpm;在Nginx中设置client_max_body_size等三项;在filesystems.php磁盘配置中添加max_file_size;最后通过分片上传路由与控制器实现大文件可靠传输。

要让Laravel应用稳定接收500MB课程视频或2GB工程图纸,必须同时突破PHP、Web服务器、框架三层限制,缺一不可。
修改PHP底层上传阈值
打开php.ini文件,定位并修改以下四行参数:
upload_max_filesize = 2048M
post_max_size = 2048M
max_execution_time = 7200
memory_limit = 2048M
注意:post_max_size必须≥upload_max_filesize,否则即使文件没超限也会被PHP直接拒绝;max_execution_time设为7200秒(2小时)是为应对弱网环境下的分片上传总耗时。
改完后重启PHP-FPM服务:systemctl restart php-fpm。
Nginx请求体与缓冲区扩容
在Nginx主配置或站点server块内添加:
client_max_body_size 2048M;
client_body_buffer_size 128M;
client_body_temp_path /var/tmp/nginx_client_body 1 2;
其中client_body_temp_path指定临时存储路径,必须确保该目录存在且nginx用户有写权限,否则大文件上传会静默失败。
执行nginx -t验证语法,再运行nginx -s reload重载配置。
Laravel磁盘配置文件大小限制
编辑config/filesystems.php,在对应磁盘配置中加入max_file_size选项:
'public' => [
'driver' => 'local',
'root' => storage_path('app/public'),
'max_file_size' => 2048 * 1024 * 1024,
// 其他配置...
],
这个配置只对Laravel层面的store()、storeAs()方法生效,不影响原始HTTP请求解析。修改后运行php artisan config:clear清除缓存。
验证临时目录可写性
创建一个测试路由,返回关键路径状态:
Route::get('/upload-check', function () {
$tmp = ini_get('upload_tmp_dir') ?: sys_get_temp_dir();
return response()->json([
'upload_tmp_dir' => $tmp,
'is_writable' => is_writable($tmp),
'disk_free' => disk_free_space($tmp) / (1024*1024*1024) . ' GB'
]);
});
访问该路由,确认is_writable为true且剩余空间>2GB。Docker环境中常见问题:【/var/tmp】目录未挂载或www-data用户无写权限。
分片上传后端路由与控制器准备
第一步:注册两条专用路由
Route::post('/api/upload/chunk', [UploadController::class, 'chunk'])->middleware('auth');
Route::post('/api/upload/merge', [UploadController::class, 'merge'])->middleware('auth');
第二步:在UploadController中定义chunk方法,禁用Laravel默认文件解析
public function chunk(Request $request)
{
// 必须用getContent()读原始流,避免request()->file()触发内存爆满
$content = $request->getContent();
$identifier = $request->input('identifier');
$index = (int)$request->input('chunkIndex');
$path = storage_path("app/chunks/{$identifier}/{$index}");
file_put_contents($path, $content);
return response()->json(['uploaded' => true]);
}
第三步:merge方法中按序拼接所有分片
public function merge(Request $request)
{
$identifier = $request->input('identifier');
$total = (int)$request->input('totalChunks');
$targetPath = storage_path("app/uploads/{$identifier}.mp4");
$fp = fopen($targetPath, 'w');
for ($i = 0; $i $chunkPath = storage_path("app/chunks/{$identifier}/{$i}");
 >fwrite($fp, file_get_contents($chunkPath));
}
fclose($fp);
return response()->json(['url' => Storage::url("uploads/{$identifier}.mp4")]);
}


















