#Downloading from "private" Folder in Laravel (Nova)
1 messages ยท Page 1 of 1 (latest)
Route::get('/stream', function () {
return response()->streamDownload(function () {
echo file_get_contents("your_file_path");
}, 'responsed_file_name.ext');
});
$downloadableFile = response()->streamDownload('app/private/applications.pdf');
Log::debug($downloadableFile);
$filename = 'bewerbungen_lans ' . Carbon::today();
$extension = '.pdf';
return Action::download($downloadableFile, $filename . $extension);```
that gives me no file as well
you tried streaming ? to see what happening?
yeah, [2023-02-06 12:47:29] local.DEBUG: HTTP/1.0 200 OK Cache-Control: no-cache, private Date: Mon, 06 Feb 2023 12:47:29 GMT
that's the log of the stream
but on "download" in the browser it always returns no file
maybe i have to ask is it generally possible to download a file if it's not in the public folder at all?
yes... thats the exact purpose of the "private" storage
i c
but you have permission setted correctly right?
which permission? folder?
yes.. i mean the file is correctly written in that folder right?
try an exists and see what happen
$downloadableFile = Storage::disk('private')->exists('applications.pdf');
i think you are misspelling the correct path
check also in your filesystem to see what "private" disk link to
@dry spoke ? still there?
yes, just in a meeting ๐
oki lemme know when you can try
@orchid marsh log says [2023-02-06 13:43:26] local.DEBUG: 1 and browser says again, no file
'driver' => 'local',
'root' => storage_path('app/private'),
'url' => env('APP_URL').'/storage',
'visibility' => 'private',
'throw' => false,
],```
that's what it filesystem looks like
oh.. isee now..
its not only called "private" .. the visibility is set to private
so the permissions will be 0600 for files.. you will not be able to "download" that file
when you store something "outside" the public folder you can already consider that as NOT public accessible. but if you set the visibility as "private" the file uploaded in that disk will be chmodded to 0600 so only the "owner" can read and write. useful if you want these files be accessible by your owner. but in this case youre trying to "serve" the files to public and the group doesnt have access.
you get what i mean?
btw if you set the "throw" to true you will probably can see the exact error..
ok, changed to public
no change at all
as well as no error in log
[2023-02-06 13:57:27] local.DEBUG: 1
only my own log again
you need to
try{
} catch(Exception $e){
return $e;
}
ok
just put the $downloadableFile = Storage::disk('private')->exists('applications.pdf'); in the try and catch?
->get
so if i do get, i get the same error as before again
so he want's to download, but can't somehow
i think we need to try streaming that file correctly.. and then try the download
public function handle(ActionFields $fields, Collection $models)
{
$file = Excel::store(new MultipleSheetsApplications($models), 'applications.pdf', 'private');
$downloadableFile = Storage::disk('private')->get('applications.pdf');
$filename = "test.pdf"; //here your carbon date things.. but lets try with simple test
$headers = [
'Content-Type' => 'application/octet-stream',
'Content-Disposition' => 'attachment; filename=' . $fileName,
];
return response( $downloadableFile, 200 , $headers);
}
i think that approach wont work.. because if it's no nova action, there won't be any response at all
but i test of course
yeah, as assumed, nothing happens if i press the according button
it just says, action was executed successfully
damn forget you were on nova
yes m8, that's the problem ๐
try catch a response()->streamDownload('app/private/applications.pdf');
instead of the storage::disk part?
yes
ok
wait mate... wondering another thing... you changed visibility to "public" but the file has been re-uploaded? could you verify that chmod of that file are 0664 or 0644 ?
drwx------ 2 tobi tobi 4096 Feb 6 20:47 private
that's the folder...
that's the file -rw-r--r-- 1 tobi tobi 50348 Feb 6 22:12 applications.pdf
yep .. its correct
can you just help me with the correct syntax for the try catch?
i barely use try catch
yep
i think i have it
try {
$downloadableFile = response()->streamDownload('app/private/applications.pdf');
} catch (Exception $e) {
return $e;
}
// Log::debug($downloadableFile);
$filename = 'bewerbungen_lans ' . Carbon::today();
$extension = '.pdf';
return Action::download($downloadableFile, $filename . $extension);```
right?
yep---
ok, no change, no error, nothing
i dont know if nova use throwable...
i think so
afaik it does
m8 brb...
}catch (\Throwable $error){
return $error
}
ok re
try {
$downloadableFile = response()->streamDownload('app/private/applications.pdf');
} catch (\Throwable $error) {
return $error;
}
// Log::debug($downloadableFile);
$filename = 'bewerbungen_lans ' . Carbon::today();
$extension = '.pdf';
return Action::download($downloadableFile, $filename . $extension);```
like this, right?
unfortunately no error log
ok
did you set Throw to true in filesystem right?
yep
and please set $filename to some test string like "test.pdf"
try {
$downloadableFile = response()->streamDownload('app/private/applications.pdf');
$filename = 'testfile.pdf';
// $extension = '.pdf';
return Action::download($downloadableFile, $filename);
} catch (\Throwable $error) {
return $error;
}```
that's the actual code right now
yep
no change at all
and ?
the stream was for the previous test
i tried this now $file = Excel::store(new MultipleSheetsApplications($models), 'applications.pdf', 'private'); try { $downloadableFile = 'testfile.pdf'; // $filename = 'testfile.pdf'; // $extension = '.pdf'; return Action::download($downloadableFile, 'test.pdf'); } catch (\Throwable $error) { return $error; }
but no change at all
you mean the applications.pdf?
wait
k
$file = Excel::store(new MultipleSheetsApplications($models), 'applications.pdf', 'private');
try {
$thefilepath = Storage::disk('private')->path('applications.pdf');
return Action::download($thefilepath , 'test.pdf');
} catch (\Throwable $error) {
return $error;
}
path* not url
you changed with path?
return $thefilepath and see what is it
$file = Excel::store(new MultipleSheetsApplications($models), 'applications.pdf', 'private');
try {
$thefilepath = Storage::disk('private')->path('applications.pdf');
//return Action::download($thefilepath , 'test.pdf');
return $thefilepath;
} catch (\Throwable $error) {
return $error;
}
where should the return appear?
in the browser
the dd doesn't work
try {
$thefilepath = Storage::disk('private')->path('applications.pdf');
dd($thefilepath);
} catch (\Throwable $error) {
return $error;
}``` like this, correct?
yeah, no dd in nova
thanks anyways..
that's some crazy stuff, right
sometimes i hate my client requested nova
there's so many restrictions
are you in Debug mode right?
yeah
just for curiosity sake ... var_dump() that variable what happen?
the var_dump should appear in the browser window as well, right?
ye
no output ๐
i really suuuuuucks
i'm already working on a solution for 1 1/2 days
that's really impossible...
this sound really weird
if the file is in public, everythings easy
but as soon it is in a private folder, nothing works anymore
$file = Excel::store(new MultipleSheetsApplications($models), 'applications.pdf', 'private');
try {
$thefilepath = Storage::disk('private')->path('applications.pdf');
//return Action::download($thefilepath , 'test.pdf');
var_dump($thefilepath);
exit;
} catch (\Throwable $error) {
return $error;
}
if it correctly upload/create the file in that disk.. its weird that it doesnt even show you the path to that file
with no error..
but the file is there, 4 sure
but probably im missing something ,, or its something Nova related..
i see it with my own eyes ๐
unfortunately no dump at all
i think you have to ask some more skilled help then mine bruh!
in laravel? approx 4/5 months
generally?
my whole life... lol.. approx 20 years
lol, i c
so you're way more experienced than me, i just started out 2 years ago finally pursuing my lifelong dream ๐
lol i see..
I think the problem is, you're trying to return the PDF from the Nova API.php in a custom tool or action right?
The steaming approach should work perfectly as that's what it's good at
yes
Is it a custom tool, or action?
custom action yes
you mean like this response()->streamDownload('app/private/applications.pdf');
Ok, so the problem is, Nova sends the request from your browser to the API, then returns the response to your browser, so any response you send, won't actually send the value back to you
ok
I'm not sure you can do it with a custom action to be honest, you need a way to return a URL that you can redirect the browser to, which will then download the PDF
ok, can you think about another approach which might work in this case?
@dry spoke : that's what a skilled developer looks like -> @desert raptor
I would:
- Define an endpoint in your normal laravel routes that takes the id of your model.
- In the controller, grab the model id and load it, and return the PDF file from storage using the Response::stream method mentioned above
this should download it for you and not store it anywhere
then to secure it, add something like either:
- Laravel signed routes (https://laravel.com/docs/9.x/urls#signed-urls)
- or a password / something
If you use signed routes, you can replace your custom action with a custom field, that just generates a signed URL to that endpoint you've defined
And people can just click "download" and it will download, and if someone hits it without a signing token, it'll 403
you just have to lock down who can see that "download" custom field
the problem, what i just think of is, how do i get the "custom" download link into the nova backend?
you get my point?
ah i see, you mean by that custom field, right?
Yeah!
Np
@desert raptor i just thought of another possibility.. in the source of Nova Actions i found there's some callback after the execution of the action.. ```` /**
* Register a callback that should be invoked after the action is finished executing.
*
* @param callable(\Illuminate\Support\Collection):mixed $callback
* @return $this
*/
public function then($callback)
{
$this->thenCallback = $callback;
return $this;
}```
but i'm not sure how / where to execute this callback, can you give me a hint?
i thought of, generating the file, put it into the public, and after the file has been downloaded and the action "finished" executing, deleting the file immediately in the callback
Yeah you could do that, but there's no guarantee that the user has downloaded the whole file before it's been deleted, and you'd have to be pretty sure that it's deleting them for it to be secure.
The one in the example above?
yes
not 100% sure as i can't see it in the documentation
where and how to call this callback?
but i think it's when you register it
ah ok
{
return [
Actions\EmailAccountProfile::make()->then(function() {
// Your stuff here
});
];
}
but that's purely a guess
ok
otherwise i'm gonna check back in the nova specific discord channel
but i try your approach first
thanks ๐
np, good luck
Have you tried the code I provided?
Perhaps you should modify the file_get_contents to storage and I ensure the code is working well whether it runs in Laravel
@dry spoke
so your approach is, to create a route and in the nova action on return redirect to that laravel route?
do i understand you right?
Just a sample code, you could create a test route for it and then you can move some code to your controllers or action
but what's your general approach? because i can't use the stream in DIRECTLY the nova action, it's not working
ok, found a solution according to all your hints, i created a protected route and make a redirect in the custom action to the download
thanks a lot for your help guys
out of ideas here