If you put a file in public
folder it will be accessible to everyone who knows the file name, because nginx/apache rewrite rules used by Laravel only apply to non-existing files, so Laravel won't even be run when accessing an existing file.
So, you still have to put restricted files somewhere out of public
folder. Maybe in storage
folder, but ultimately it doesn't matter.
And yes, you should just use Response::download
.
Make a small FileController
:
class FileController extends Controller {
public function __construct()
{
$this->middleware('auth');
}
public function getFile($filename)
{
return response()->download(storage_path($filename), null, [], null);
}
}
The fourth argument of download()
being null
prevents the Content-Disposition
header being set to attachment
. So your browser won't ask you save the file, but just show it.
Then add a route:
Route::get('file/{filename}', 'FileController@getFile')->where('filename', '^[^/]+$');
And that's it. Now, your authenticated users can download files from storage
folder (but not its subfolders) by calling http://yoursite.com/file/secret.jpg
. Add you can use this URL in src
attribute of an image tag.
Xum said:
If you put a file in
public
folder it will be accessible to everyone who knows the file name, because nginx/apache rewrite rules used by Laravel only apply to non-existing files, so Laravel won't even be run when accessing an existing file.So, you still have to put restricted files somewhere out of
public
folder. Maybe instorage
folder, but ultimately it doesn't matter.And yes, you should just use
Response::download
.Make a small
FileController
:class FileController extends Controller { public function __construct() { $this->middleware('auth'); } public function getFile($filename) { return response()->download(storage_path($filename), null, [], null); } }
The fourth argument of
download()
beingnull
prevents theContent-Disposition
header being set toattachment
. So your browser won't ask you save the file, but just show it.Then add a route:
Route::get('file/{filename}', 'FileController@getFile')->where('filename', '^[^/]+$');
And that's it. Now, your authenticated users can download files from
storage
folder (but not its subfolders) by callinghttp://yoursite.com/file/secret.jpg
. Add you can use this URL insrc
attribute of an image tag.
Perfect, this seems to work just great. Also I didn't know about the 4th argument, so that makes it even better. I set it to 'inline' and I get it to be viewed in the browser.
Things are working great now.
Thanks!
Great Solution!
I needed to be able to specify a folder so...
Route:
Route::get('file/{foldername}/{filename}', 'FileController@getFile')->where('filename', '^[^/]+$');
Controller:
public function getFile($foldername,$filename)
{
$fullpath="{$foldername}/{$filename}";
return response()->download(storage_path($fullpath), null, [], null);
}
Great question and answer!
if you're looking for a file within the subfolder (i.e. personal) like http://yoursite.com/file/personal/secret.jpg
the root above won't work.
Change the where to:
->where('filename', '^(.+)\/([^\/]+)$')
Sign in to participate in this thread!
The Laravel portal for problem solving, knowledge sharing and community building.
The community