Laravel9文件上传存储路径不符、上传文件变为.tmp格式问题
问题根因
两个异常来自同一个代码bug,和Laravel 8/9版本差异没有直接关系:
- PHP变量名大小写敏感,你的代码里验证结果变量名前后不一致:验证时赋值的是首字母大写的
$ValidatedData,处理图片上传时却给首字母小写的$validatedData写入存储路径,最终调用Menus::create()传入的是大写开头的变量,这个变量里的image字段值没有被store()方法返回的路径覆盖,仍然是请求中携带的原生临时上传文件实例。 - 框架在写入数据库时会自动把文件对象转成字符串,取值就是PHP上传流程生成的系统临时目录下的
.tmp后缀临时文件路径,这就直接导致两个现象:一是存储路径和配置的public磁盘预期路径完全不符,二是所有记录里的文件路径都是.tmp后缀。
修复步骤
1. 统一变量名,修正核心逻辑
把store方法里的变量名全部统一为小写开头的$validatedData,同时显式指定文件存储使用public磁盘,避免版本默认配置差异影响,修正后的代码如下:
public function store(Request $request) { // 统一使用小写开头的变量名 $validatedData = $request->validate([ 'title' => 'required|max:255', 'slug' => 'required|unique:menus', 'categories_id' => 'required', 'deskripsi' => 'required', 'is_order' => 'required', 'most' => 'required', 'price' => 'required', 'image' => 'image|file|max:1024' ]); if($request->file('image')){ // 显式指定public磁盘,存储到menus目录下 $validatedData['image'] = $request->file('image')->store('menus', 'public'); } $validatedData['users_id'] = Auth::user()->id; $validatedData['excerpt'] = Str::limit(strip_tags($request->deskripsi), 100); Menus::create($validatedData); // 辅助函数统一用小写写法 return redirect('/dashboard/menus')->with('success', 'Tugas Baru Telah Ditambahkan!'); }
2. 补全表单文件上传必填属性
你贴出的表单片段缺少form标签的必要配置,文件上传必须给form标签添加enctype="multipart/form-data"属性,否则服务端无法正常接收上传的文件,form标签参考写法:
<form method="POST" action="/dashboard/menus" enctype="multipart/form-data"> <!-- 原有表单项保留 --> <div class="mb-3"> <label for="image" class="form-label">Size Max. 1mb</label> <input class="form-control @error('image') is-invalid @enderror" type="file" name="image" id="image"> @error('image') <div class="invalid-feedback"> {{ $message }} </div> @enderror </div> </form>
3. 生成存储软链接
由于你使用public磁盘存储文件,需要执行artisan命令生成storage目录到public目录的软链接,否则上传的文件无法通过web路径正常访问:
php artisan storage:link
补充说明:Laravel 9确实调整了文件系统的默认配置键名,从Laravel 8的
FILESYSTEM_DRIVER改为FILESYSTEM_DISK,你当前.env里的配置是正确的,不需要修改。
内容的提问来源于stack exchange,提问作者Nasa Wiko
相关产品推荐
相关产品推荐

