Laravel 8.55队列处理S3上传文件生产环境报文件不存在错误
Laravel 8 队列任务Heroku部署时Laravel-Excel报文件不存在故障排查
问题背景
接手的项目基于Laravel 8.55开发,包含一个网页上传CSV触发的队列任务,执行流程如下:
- CSV文件上传至S3存储桶
- 借助Laravel-Excel完成文件解析处理,更新对应数据库条目
- 向用户发送任务完成通知邮件
- 删除S3中存储的原始CSV文件
本地开发环境为Windows11(PhpStorm)+ MySQL,使用php artisan serve作为Web服务器,该队列任务在本地运行完全符合预期。
故障现象
部署到Heroku生产环境后:
- 文件可成功上传至目标S3存储桶
- 后续队列任务执行失败,失败记录写入
failed_jobs表 - Bugsnag上报错误信息如下:
Illuminate\Contracts\Filesystem\FileNotFoundExceptionMaatwebsite\Excel\Jobs\ReadChunk File not found at path: laravel-excel-3svOWxojWikYEuWZuBBBHlbXl6WpK7Xb.csv
触发该任务的上传代码片段:
$file = $request->file('filename'); $f_ori_name = $file->getClientOriginalName(); $extension = $file->getClientOriginalExtension(); $file_name = Str::random(40).'.'.$extension; $tmp_path = Storage::disk('s3_temp')->put($file_name, file_get_contents($file->getRealPath())); $path = Storage::disk('s3_temp')->path($file_name); $var = (new MembersImport($currentPerson, $import_detail))->queue($path, 's3_temp') ->chain([ new ImportDetailsUpdateJob($import_detail), new NotifyUserOfCompletedImport($currentPerson, $import_detail), function () use ($path) { Storage::disk('s3_temp')->delete($path); } ])->onConnection('database') ->onQueue('default');
故障根因
- Heroku的dyno文件系统是临时隔离的:Web dyno和Queue Worker dyno的本地文件系统不共享,Laravel-Excel默认会将远程文件拉取到本地临时目录生成
laravel-excel-xxx.csv格式的临时分块文件,Web进程生成的临时文件Worker进程完全无法访问。 - 代码中对S3磁盘错误调用了
path()方法:S3作为对象存储不存在本地绝对路径概念,path()返回的本地路径在Worker进程中无对应有效文件。 - 队列链中的删除逻辑引用了错误的路径变量,可能触发提前删除文件的逻辑。
修复方案
- 修正S3文件传参逻辑:删除
$path = Storage::disk('s3_temp')->path($file_name);的赋值,调用queue()方法时第一个参数直接传S3对象key也就是$file_name即可,因为第二个参数已经指定磁盘为s3_temp,Laravel-Excel会自动通过S3 API读取对象,不需要本地路径。 - 修改Laravel-Excel临时文件配置:打开
config/excel.php,找到temporary_files配置项,将临时文件磁盘设置为S3共享存储,避免使用本地临时目录导致跨dyno访问失败,配置参考:
'temporary_files' => [ 'local_path' => storage_path('framework/cache/laravel-excel'), 'disk' => 's3_temp', // 替换为你的S3临时存储磁盘名 ],
- 修正队列链的删除逻辑:删除闭包中传入的
$path变量,直接使用$file_name作为删除参数,即Storage::disk('s3_temp')->delete($file_name);,避免路径错误导致的误删或者删除失败。 - 校验Heroku环境配置:确认Queue Worker dyno的环境变量(尤其是S3访问密钥、区域、桶名配置)和Web dyno完全一致,同时确认
config/filesystems.php中s3_temp磁盘生产环境使用s3驱动而非本地驱动。
内容的提问来源于stack exchange,提问作者Phil
相关产品推荐
相关产品推荐

