Laravel 5.7 : 404 or 403 on storage/app/private whereas it works on storage/app/public
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).
laravel laravel-5 laravel-5.7
add a comment |
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).
laravel laravel-5 laravel-5.7
add a comment |
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).
laravel laravel-5 laravel-5.7
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).
laravel laravel-5 laravel-5.7
laravel laravel-5 laravel-5.7
edited Nov 23 '18 at 11:00
HelloWorld
asked Nov 22 '18 at 2:23
HelloWorldHelloWorld
1,005612
1,005612
add a comment |
add a comment |
1 Answer
1
active
oldest
votes
You can use Storage::download('filename.xyz')
instead of generating a URL with Storage::url('filename.xyu')
. This will send the file as content of the response. It may be resource intensive for large files though.
Thanks @Namoshek! I updated my question with the solution I used based on your answer.
– HelloWorld
Nov 23 '18 at 10:51
Note about your comment in the solutionSo I check twice but that's not a problem because there is very low traffic (once a week or so)
: It is actually required for you to check the permissions twice (at least from what I got from the requirements). Otherwise a user with the permission to see or download the file could simply send the link to someone else. And to be fair, such a permission check does not cost a lot of resources at all.
– Namoshek
Nov 23 '18 at 11:08
add a comment |
Your Answer
StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");
StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});
function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53423032%2flaravel-5-7-404-or-403-on-storage-app-private-whereas-it-works-on-storage-app%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
1 Answer
1
active
oldest
votes
1 Answer
1
active
oldest
votes
active
oldest
votes
active
oldest
votes
You can use Storage::download('filename.xyz')
instead of generating a URL with Storage::url('filename.xyu')
. This will send the file as content of the response. It may be resource intensive for large files though.
Thanks @Namoshek! I updated my question with the solution I used based on your answer.
– HelloWorld
Nov 23 '18 at 10:51
Note about your comment in the solutionSo I check twice but that's not a problem because there is very low traffic (once a week or so)
: It is actually required for you to check the permissions twice (at least from what I got from the requirements). Otherwise a user with the permission to see or download the file could simply send the link to someone else. And to be fair, such a permission check does not cost a lot of resources at all.
– Namoshek
Nov 23 '18 at 11:08
add a comment |
You can use Storage::download('filename.xyz')
instead of generating a URL with Storage::url('filename.xyu')
. This will send the file as content of the response. It may be resource intensive for large files though.
Thanks @Namoshek! I updated my question with the solution I used based on your answer.
– HelloWorld
Nov 23 '18 at 10:51
Note about your comment in the solutionSo I check twice but that's not a problem because there is very low traffic (once a week or so)
: It is actually required for you to check the permissions twice (at least from what I got from the requirements). Otherwise a user with the permission to see or download the file could simply send the link to someone else. And to be fair, such a permission check does not cost a lot of resources at all.
– Namoshek
Nov 23 '18 at 11:08
add a comment |
You can use Storage::download('filename.xyz')
instead of generating a URL with Storage::url('filename.xyu')
. This will send the file as content of the response. It may be resource intensive for large files though.
You can use Storage::download('filename.xyz')
instead of generating a URL with Storage::url('filename.xyu')
. This will send the file as content of the response. It may be resource intensive for large files though.
answered Nov 22 '18 at 5:43
NamoshekNamoshek
3,0462819
3,0462819
Thanks @Namoshek! I updated my question with the solution I used based on your answer.
– HelloWorld
Nov 23 '18 at 10:51
Note about your comment in the solutionSo I check twice but that's not a problem because there is very low traffic (once a week or so)
: It is actually required for you to check the permissions twice (at least from what I got from the requirements). Otherwise a user with the permission to see or download the file could simply send the link to someone else. And to be fair, such a permission check does not cost a lot of resources at all.
– Namoshek
Nov 23 '18 at 11:08
add a comment |
Thanks @Namoshek! I updated my question with the solution I used based on your answer.
– HelloWorld
Nov 23 '18 at 10:51
Note about your comment in the solutionSo I check twice but that's not a problem because there is very low traffic (once a week or so)
: It is actually required for you to check the permissions twice (at least from what I got from the requirements). Otherwise a user with the permission to see or download the file could simply send the link to someone else. And to be fair, such a permission check does not cost a lot of resources at all.
– Namoshek
Nov 23 '18 at 11:08
Thanks @Namoshek! I updated my question with the solution I used based on your answer.
– HelloWorld
Nov 23 '18 at 10:51
Thanks @Namoshek! I updated my question with the solution I used based on your answer.
– HelloWorld
Nov 23 '18 at 10:51
Note about your comment in the solution
So I check twice but that's not a problem because there is very low traffic (once a week or so)
: It is actually required for you to check the permissions twice (at least from what I got from the requirements). Otherwise a user with the permission to see or download the file could simply send the link to someone else. And to be fair, such a permission check does not cost a lot of resources at all.– Namoshek
Nov 23 '18 at 11:08
Note about your comment in the solution
So I check twice but that's not a problem because there is very low traffic (once a week or so)
: It is actually required for you to check the permissions twice (at least from what I got from the requirements). Otherwise a user with the permission to see or download the file could simply send the link to someone else. And to be fair, such a permission check does not cost a lot of resources at all.– Namoshek
Nov 23 '18 at 11:08
add a comment |
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53423032%2flaravel-5-7-404-or-403-on-storage-app-private-whereas-it-works-on-storage-app%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown