Laravel 5.7 :storage/app/private 上的 404 或 403 而它在 storage/app/public 上有效

Laravel 5.7 : 404 or 403 on storage/app/private whereas it works on storage/app/public

我正在努力为用户提供一个 link 文件,他们可以在登录后下载该文件。我读过 this and

所以在我的 app/storage 文件夹下,我在 "public" 旁边创建了一个 "private" 目录。它里面有一个包含 "fileA.tar.gz" 的子文件夹 "A"(我也试过一个简单的 test.txt,但运气不好)。

MyLaravelApp/
├── storage/
│   ├── public/
│   ├── private/
│        └── A/
│            └──fileA.tar.gz 

在我的控制器中我这样做:

$softwarePath = "private/A/fileA.tar.gz";

$urlToArchive = \Storage::disk('local')->url(
                                $softwarePath);

$exists = \Storage::disk('local')->exists($softwarePath); // returns true

但是在视图中,当我点击 link http://127.0.0.1:8000/storage/private/A/fileA.tar.gz 我得到 404 尽管 exists 函数 returns true.

所以我尝试在 /config/filesystems.php 中定义一个直接 "short-cut" 到我的 "private" 文件夹:

'private' => [
    'driver' => 'local',
    'root' => storage_path('app/private'),
    'url' => env('APP_URL').'/privateDownload',
    'visibility' => 'public',
],

并在控制器中进行了以下更改:

$softwarePath = "A/fileA.tar.gz";

$urlToArchive = \Storage::disk('private')->url($softwarePath);

$exists = \Storage::disk('private')->exists($softwarePath); // keeps returning true

但是现在当我点击生成的 link http://localhost/privateDownload/A/fileA.tar.gz 时我得到 403(注意没有端口地址的本地主机),如果我将地址更改为 localhost:8000 我得到 404返回。

上述控制器的路由是:

Route::get('/account', 'AccountController@showAccountDetails')->middleware('auth');

而且我还尝试删除 middleware('auth') 并访问 private/A/fileA.tar.gz 但不幸 (404)。

请注意:如果我保留相同的子目录层次结构并将其移动到 public 下,例如:

MyLaravelApp/
├── storage/
│   ├── public/
│        └── A/
│            └──fileA.tar.gz 
│   ├── private/

没有问题,可以下载文件。这没什么意思,因为我想防止在未登录的情况下下载此文件。

根据 doc 和其他 SO 答案,似乎可以访问与 public 不同的目录。如何做呢 ?为什么 exists() return 是真的,而我得到的是 404?我的设置/代码失败实际上是什么?

感谢任何帮助!

解决方案

根据@Namoshek 的回答,这是我所做的(作为记录):

在前面提到的控制器中,我只是检查了用户是否有权下载fileA。如果是这样,那么我 return 一个视图有一个 link 到一个名为 downloadFileA 的路由,该路由指向一个函数 downloadFileA 仍然在同一个上述控制器中。

最后在函数 downloadFileA I return \Storage::disk('private')->download('fileA') 检查用户是否有权下载文件后。所以我检查了两次,但这不是问题,因为流量非常低(每周一次左右)。

您可以使用 Storage::download('filename.xyz') 而不是使用 Storage::url('filename.xyu') 生成 URL。这会将文件作为响应的内容发送。不过,对于大文件来说,它可能是资源密集型的。