Laravel部署Kinsta后public目录文件存储报错求助
Laravel部署Kinsta后文件上传写入目录失败排查
报错信息
Symfony\Component\HttpFoundation\File\Exception\FileException: Unable to write in the "/app/public/media" directory. in file /app/vendor/symfony/http-foundation/File/File.php on line 131
问题代码
if (!File::isDirectory($directory)) { File::makeDirectory($directory, 0755, true, true); } $file = $request->file('file'); $fileName = time() . '_' . $this->cleanString($file->getClientOriginalName()); // 可自定义文件名 $file->move(public_path('media'), $fileName);
核心原因
Kinsta的应用容器采用只读文件系统设计:
/app/public属于代码部署目录,运行时无写入权限,本地环境无此限制,因此代码在本地正常、线上报错。- 代码中定义的
$directory变量未实际使用,导致目录存在性判断逻辑无效,直接尝试写入只读的public/media目录。
解决方案
方案1:改用Kinsta允许的可写目录(持久化存储)
Kinsta仅允许/storage和/tmp目录写入,其中/storage为持久化目录(容器重启不丢失文件)。修改代码如下:
// 定义存储目录为storage下的media文件夹 $directory = storage_path('media'); if (!File::isDirectory($directory)) { File::makeDirectory($directory, 0755, true, true); } $file = $request->file('file'); $fileName = time() . '_' . $this->cleanString($file->getClientOriginalName()); // 移动到可写的storage/media目录 $file->move($directory, $fileName); // 如需前端访问文件,可添加路由返回文件 // Route::get('media/{filename}', function ($filename) { // $path = storage_path('media/' . $filename); // if (!File::exists($path)) abort(404); // return response()->file($path); // })->name('media.view');
方案2:使用Kinsta对象存储(推荐生产环境)
若坚持要对外暴露文件且不想用本地存储,可使用Kinsta提供的S3兼容对象存储:
- 在Kinsta控制台配置对象存储服务
- 修改
config/filesystems.php,添加S3磁盘配置 - 调整上传代码使用云存储:
use Illuminate\Support\Facades\Storage; $file = $request->file('file'); $fileName = time() . '_' . $this->cleanString($file->getClientOriginalName()); // 上传到对象存储的media目录 Storage::disk('s3')->putFileAs('media', $file, $fileName); // 获取文件公开访问链接 $url = Storage::disk('s3')->url('media/' . $fileName);
内容的提问来源于stack exchange,提问作者Salam Aslam
相关产品推荐
相关产品推荐

