I am struggling to offer the user a link to a file that they can download when logged in. I read this and that (because eventually I want to protect the file from public access).
So under my app /storage folder I created a "private" directory next to "public". Inside it there is a subfolder "A" containing a "fileA.tar.gz" (I also tried with a simple test.txt without luck).
MyLaravelApp/
├── storage/
│ ├── public/
│ ├── private/
│ └── A/
│ └──fileA.tar.gz
In my controller I do :
$softwarePath = "private/A/fileA.tar.gz";
$urlToArchive = \Storage::disk('local')->url(
$softwarePath);
$exists = \Storage::disk('local')->exists($softwarePath); // returns true
But in the view when I click on the link http://127.0.0.1:8000/storage/private/A/fileA.tar.gz
I get 404 although the exists
function returns true
.
So I tried to define in /config/filesystems.php a direct "short-cut" to my "private" folder :
'private' => [
'driver' => 'local',
'root' => storage_path('app/private'),
'url' => env('APP_URL').'/privateDownload',
'visibility' => 'public',
],
and made the following changes in the controller :
$softwarePath = "A/fileA.tar.gz";
$urlToArchive = \Storage::disk('private')->url($softwarePath);
$exists = \Storage::disk('private')->exists($softwarePath); // keeps returning true
But now I get 403 when I click on the generated link http://localhost/privateDownload/A/fileA.tar.gz
(note the localhost without port address) and if I change the address to localhost:8000 I get the 404 back.
The route to the aforementioned controller is :
Route::get('/account', 'AccountController@showAccountDetails')->middleware('auth');
And I also tried to remove the middleware('auth')
and access to private/A/fileA.tar.gz
without luck (404).
Please note : if I keep the same subdirectory hierachy and moved it under public like :
MyLaravelApp/
├── storage/
│ ├── public/
│ └── A/
│ └──fileA.tar.gz
│ ├── private/
There is no issue, and the file can be downloaded. This is not interesting because I want to prevent this file from being downloaded without being logged in.
According to the doc and other SO answers it seems possible to access to a different directory than public
. How can it be done ? Why exists()
returns true whereas I get 404 then ? What's my setup / code failure actually?
Any help appreciated!
Solution
Based on @Namoshek's answer, here is what I did (for the records) :
In the aforementioned controller I simply checked whether or not the user has the right to download fileA. If so then I return a view which has a link to a route named downloadFileA
that points to a function downloadFileA
still in the same aforementioned controller.
Finally in the function downloadFileA
I return \Storage::disk('private')->download('fileA')
after checking whether the user is entitled or not to download the file. So I check twice but that's not a problem because there is very low traffic (once a week or so).