无法在 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);
    }
}