通过接口上传的文件是一个.glb
后缀结尾的3d模型文件,保存文件的代码如下:
$dataPath = Storage::disk('public')->putFile('models', $request->file('model'));
使用的是Storage
门面的putFile
方法,但是保存之后的文件名后缀是以.bin
结尾的,而不是原文件的.glb
,这样子当我把$dataPath
变量入库,后面前端需要数据的时候拿到的就是.bin
后缀的路径,造成了模型在前端无法正常展示的问题。
问题的原因在于putFile
方法默认会去猜文件的类型,然后使用相应的后缀名,而不是保留原来的用户名。这一点在laravel的官网文档里面有指出:
By default, the putFile method will generate a unique ID to serve as the file name. The file's extension will be determined by examining the file's MIME type. The path to the file will be returned by the putFile method so you can store the path, including the generated file name, in your database.
通过查看这个方法的源码也可以找到原因:
/**
* Store the uploaded file on the disk.
*
* @param string $path
* @param \Illuminate\Http\File|\Illuminate\Http\UploadedFile $file
* @param array $options
* @return string|false
*/
public function putFile($path, $file, $options = [])
{
return $this->putFileAs($path, $file, $file->hashName(), $options);
}
hashName
方法的代码:
/**
* Get a filename for the file.
*
* @param string $path
* @return string
*/
public function hashName($path = null)
{
if ($path) {
$path = rtrim($path, '/').'/';
}
$hash = $this->hashName ?: $this->hashName = Str::random(40);
if ($extension = $this->guessExtension()) {
$extension = '.'.$extension;
}
return $path.$hash.$extension;
}
putFile
方法是没有传入文件名的,所以hasName
会使用Str
helper创建一个40位的随机字符串作为文件名,然后使用gesssExtension
方法去“猜”此文件的后缀。
找到原因之后将原来的代码改造一下就可以解决问题:
$dataNewName = Str::random(40) . '.' .$request->file('model')->getClientOriginalExtension();
$dataPath = Storage::disk('public')->putFileAs('models', $request->file('model'), $dataNewName);
这里使用了getClientOriginalExtension
方法来获取原始文件的后缀,然后使用putFileAs
方法来保存文件,同时指定文件名。
参考资料:
Laravel - File Storage
网友评论