Laravel 5.7:存储/应用/私有上为404或403,而存储/应用/公共上为

时间:2018-11-22 02:23:05

标签: laravel laravel-5 laravel-5.7

我正在努力为用户提供指向他们登录时可以下载的文件的链接。我读了thisthat (because eventually I want to protect the file from public access)

因此,在我的应用程序/ storage文件夹下,我在“公共”旁边创建了一个“私有”目录。在其中有一个包含“ 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

但是在视图中,当我单击链接http://127.0.0.1:8000/storage/private/A/fileA.tar.gz时,尽管exists函数返回了true,但我得到了404。

因此,我尝试在/config/filesystems.php中为我的“私人”文件夹定义直接的“快捷方式”:

'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

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

到上述控制器的路由为:

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

我还尝试删除middleware('auth')并访问private/A/fileA.tar.gz,但没有运气(404)。

请注意:如果我保留相同的子目录,并将其移至公共位置,如:

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

没有问题,可以下载文件。这并不有趣,因为我想防止未登录就下载该文件。

根据doc和其他SO答案,似乎可以访问不同于public的目录。怎么做到呢 ?为什么exists()返回true,而我却得到404?究竟我的设置/代码失败是什么?

任何帮助表示赞赏!

解决方案

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

在上述控制器中,我只是简单地检查了用户是否有权下载文件A。如果是这样,那么我返回一个视图,该视图具有指向名为downloadFileA的路由的链接,该路由指向仍在上述控制器中的函数downloadFileA

最后,在功能downloadFileA中,在检查用户是否有权下载文件后,我返回\Storage::disk('private')->download('fileA')。因此,我检查了两次,但这不是问题,因为流量非常低(一周左右)。

1 个答案:

答案 0 :(得分:1)

您可以使用Storage::download('filename.xyz')代替使用Storage::url('filename.xyu')生成URL。这将发送文件作为响应的内容。不过,对于大文件而言,这可能会占用大量资源。