无法在 Laravel 中检索名称 public 存储中包含西里尔字母的文件
Files with cyrillic letters in name public storage could not be retrieved in Laravel
如果文件名称中包含西里尔字母,我会收到找不到对象错误。
我正在使用带有 public 存储和符号 link 到 public 目录的标准配置,并使用以下代码将 url 检索到文件:
$url = Illuminate\Support\Facades\Storage::disk(config('filesystems.default'))
->url($file->getDiskPath());
提前感谢您的帮助!
最后我想出了一些适合我需要的解决方案。希望对以后遇到它的人有所帮助:
首先,我为我的项目添加了对 slug 的支持。幸运的是,我已经在使用 Spartie/laravel-tags 包,这就像在我的模型中添加 HasSlug
特征一样简单。
然后我写了一个函数,它给了我 url 比如:
baseUrl + '/get-item/' + item.slug.en + '/' + item.item_media.id
然后我创建了控制器来捕获 GET
对 URL 的请求:
public function getItem($slug, $mediaId)
{
$media = Media::find($mediaId);
if($media !== null){
$fileName = $media->filename;
$filePath = $media->directory;
$fileExt = $media->extension;
$fileMime = $media->mime_type;
$path = Storage::disk(config('filesystems.default'))->path($filePath . '/'. $fileName . '.' . $fileExt);
if(!File::exists($path)) abort(404);
$headers = array(
'Content-Type: ' . $fileMime,
);
return response()->download($path, $fileName, $headers);
}
}
当然 $slug
参数在控制器定义中是多余的,但是在 URL 中包含此字符串对于 SEO 目的非常有用。
更新
问题不在于俄语(或西里尔语)。事实上 Larave 确实在路由中正确处理了它。实际问题是编码的特殊字符() and following link 给了我一个非常优雅的解决方法的提示:
我将 url 重写为以下内容:
baseUrl + '/download?file=' + directory + filename + '.' + extension
之后我的控制器方法改变如下:
public function getItem(Request $request)
{
$media = null;
if($request->has('file')) {
$name = $request->get('file');
$media = Media::forPathOnDisk(config('filesystems.default'), $name)->first();
}
if($media !== null){
$fileName = $media->filename;
$filePath = $media->directory;
$fileExt = $media->extension;
$fileMime = $media->mime_type;
$path = Storage::disk(config('filesystems.default'))->path($filePath . '/'. $fileName . '.' . $fileExt);
if(!File::exists($path)) abort(404);
$headers = array(
'Content-Type: ' . $fileMime,
);
return response()->download($path, $fileName, $headers);
}
}
如果文件名称中包含西里尔字母,我会收到找不到对象错误。 我正在使用带有 public 存储和符号 link 到 public 目录的标准配置,并使用以下代码将 url 检索到文件:
$url = Illuminate\Support\Facades\Storage::disk(config('filesystems.default'))
->url($file->getDiskPath());
提前感谢您的帮助!
最后我想出了一些适合我需要的解决方案。希望对以后遇到它的人有所帮助:
首先,我为我的项目添加了对 slug 的支持。幸运的是,我已经在使用 Spartie/laravel-tags 包,这就像在我的模型中添加 HasSlug
特征一样简单。
然后我写了一个函数,它给了我 url 比如:
baseUrl + '/get-item/' + item.slug.en + '/' + item.item_media.id
然后我创建了控制器来捕获 GET
对 URL 的请求:
public function getItem($slug, $mediaId)
{
$media = Media::find($mediaId);
if($media !== null){
$fileName = $media->filename;
$filePath = $media->directory;
$fileExt = $media->extension;
$fileMime = $media->mime_type;
$path = Storage::disk(config('filesystems.default'))->path($filePath . '/'. $fileName . '.' . $fileExt);
if(!File::exists($path)) abort(404);
$headers = array(
'Content-Type: ' . $fileMime,
);
return response()->download($path, $fileName, $headers);
}
}
当然 $slug
参数在控制器定义中是多余的,但是在 URL 中包含此字符串对于 SEO 目的非常有用。
更新
问题不在于俄语(或西里尔语)。事实上 Larave 确实在路由中正确处理了它。实际问题是编码的特殊字符(
我将 url 重写为以下内容:
baseUrl + '/download?file=' + directory + filename + '.' + extension
之后我的控制器方法改变如下:
public function getItem(Request $request)
{
$media = null;
if($request->has('file')) {
$name = $request->get('file');
$media = Media::forPathOnDisk(config('filesystems.default'), $name)->first();
}
if($media !== null){
$fileName = $media->filename;
$filePath = $media->directory;
$fileExt = $media->extension;
$fileMime = $media->mime_type;
$path = Storage::disk(config('filesystems.default'))->path($filePath . '/'. $fileName . '.' . $fileExt);
if(!File::exists($path)) abort(404);
$headers = array(
'Content-Type: ' . $fileMime,
);
return response()->download($path, $fileName, $headers);
}
}