Laravel Backpack图片上传时value为base64如何获取原始文件名
问题原因
- Laravel Backpack 默认的
image字段类型为了支持前端即时裁剪、预览功能,会在用户选择图片后直接在前端将文件转成 base64 编码提交到后端,所以修改器里拿到的$value不是标准的Illuminate\Http\UploadedFile实例,而是 base64 字符串,这也是你调用getClientOriginalName()、getClientOriginalExtension()这类文件方法无法生效的核心原因。 - 你当前的
generateFileName方法本身存在逻辑问题:第一行已经获取了原始文件名的变量,第二行直接用Str::random(20)把变量值覆盖了,就算能正常拿到原始文件名也会被随机字符串替换。
解决方案
根据你是否需要使用前端裁剪功能,可选择以下两种方案:
方案1:不需要前端裁剪,使用原生文件上传(实现最简单)
首先在你的 CRUD 控制器的 setupCreateOperation / setupUpdateOperation 方法中,把图片字段的定义调整为带 withFiles() 配置的上传类型:
CRUD::field('image') ->type('upload') ->withFiles([ 'disk' => 'uploads', 'path' => 'storage/services/' . date('FY'), 'deleteWhenEntryIsDeleted' => true ]);
调整后修改器接收到的 $value 就是标准的 UploadedFile 实例,你可以直接获取原始文件名,修改后的修改器代码如下:
public function setImageAttribute($value) { $attribute_name = "image"; $disk = "uploads"; $destination_path = 'storage/services/' . date('FY') . DIRECTORY_SEPARATOR; // 清空字段时删除旧文件 if ($value == null) { Storage::disk($disk)->delete($this->{$attribute_name}); $this->attributes[$attribute_name] = null; return; } // 此时$value为UploadedFile实例,可直接调用文件方法 if ($value instanceof \Illuminate\Http\UploadedFile) { // 提取原始文件名(不含后缀)和后缀 $originalName = pathinfo($value->getClientOriginalName(), PATHINFO_FILENAME); $extension = $value->getClientOriginalExtension(); $filename = $originalName; // 处理重名问题:如果文件已存在,追加数字后缀 $counter = 1; while (Storage::disk($disk)->exists($destination_path . $filename . '.' . $extension)) { $filename = $originalName . '-' . $counter; $counter++; } // 存储文件并调整图片方向 $fullPath = $value->storeAs($destination_path, $filename . '.' . $extension, $disk); $image = InterventionImage::make(Storage::disk($disk)->path($fullPath))->orientate(); $image->save(); $this->attributes[$attribute_name] = $fullPath; } }
修改后可删除你之前写的 generateFileName 方法,逻辑已经整合到修改器中。
方案2:需要保留前端裁剪功能
如果必须使用默认的 base64 上传逻辑保留前端裁剪能力,需要修改前端上传逻辑,把原始文件名和 base64 内容一起提交到后端:
- 给图片字段添加自定义属性标记需要携带文件名:
CRUD::field('image') ->type('image') ->attributes(['data-with-origin-name' => true]);
- 添加自定义前端JS,在用户选择图片后把原始文件名和base64内容一起封装提交,后端修改器接收后拆分出原始文件名即可按规则命名存储。
内容的提问来源于stack exchange,提问作者MO Nabil
相关产品推荐
相关产品推荐

