如何用Storage::putFile存储Guzzle Stream并解决hashName不存在报错
问题根因
call_user_func_array() expects parameter 1 to be a valid callback, class 'GuzzleHttp\Psr7\Stream' does not have a method 'hashName'
这个报错是因为Laravel的Storage::putFile()方法默认要求传入的第二个参数是Illuminate\Http\UploadedFile实例,该类内置了hashName()方法用于生成随机哈希文件名,而你传入的Guzzle Stream对象没有该方法,所以调用失败。
解决方案
方案1:使用Storage::put()方法直接存储流(推荐)
put方法原生支持传入PSR-7标准的流实例,你只需要自行指定存储路径和文件名即可,代码修改如下:
use Illuminate\Support\Str; public function setCVAttribute($value) { if($value != null) { if(isset($this->attributes['cv']) && Storage::exists($this->attributes['cv'])) { Storage::delete($this->attributes['cv']); } // 可从邮件解析的附件元数据中获取原始后缀、mime类型,替换示例中的固定值 $extension = 'pdf'; $fileName = Str::random(40) . '.' . $extension; $path = 'cvs/' . $fileName; // 直接传入Guzzle Stream实例即可 Storage::put($path, $value); $this->attributes['cv'] = $path; } }
方案2:封装为UploadedFile实例适配putFile逻辑
如果业务需要保留putFile的自动命名逻辑,可以先把流写入临时文件再封装为UploadedFile实例:
use Illuminate\Http\UploadedFile; use Illuminate\Support\Facades\File; public function setCVAttribute($value) { if($value != null) { if(isset($this->attributes['cv']) && Storage::exists($this->attributes['cv'])) { Storage::delete($this->attributes['cv']); } // 生成临时文件存储流内容 $tmpPath = tempnam(sys_get_temp_dir(), 'cv'); file_put_contents($tmpPath, $value); // 实例化UploadedFile,mime类型可从附件元数据获取替换 $uploadedFile = new UploadedFile($tmpPath, 'cv.pdf', 'application/pdf', null, true); $path = Storage::putFile('cvs', $uploadedFile); // 清理临时文件 File::delete($tmpPath); $this->attributes['cv'] = $path; } }
内容的提问来源于stack exchange,提问作者NicolasSC
相关产品推荐
相关产品推荐

