How to map private resource to public in Laravel? - php

I have been using the Storage facade to store user profile pictures and they are being saved inside the Storage folder in the project. The problem is that I cannot directly display these photos because of the permissions of the storage folder, I have read people mentioning mapping a private resource to a public one but I am unsure how to exactly do this.
For example here is a snippet of code I am using to save a photo upload
if (Storage::disk('public')->has($usersname)) {
Storage::delete($usersname. '.' . $ext);
}
Storage::disk('public')->put($filename, File::get($file));
But in the view I cannot directly display this now saved resource

You could use two different approaches:
#1: define a new disk for your storage that is linked to a directory inside the public folder. Something like public/profile_pics. All you need to do, then, is to use that disk while uploading profile pictures. This way, they will be accessible anywhere;
#2: if you don't want to expose your files directly, define a private disk for your profile pics, and then create a route (maybe /profile-pic/{userId}) that will serve a specific response with the image data and the right headers;
EDIT: Laravel uses Flysystem for the storage. So, if you take a look to the API page of the project you can find the
$mimetype = $filesystem->getMimetype('path/to/file.txt');
example that can help you to get the right mimetype for the response you're going to build (in case you're implementing #2).
Hope it helps :)

The public disk is meant for files that are going to be publicly accessible. By default, the public disk uses the local driver and stores these files in storage/app/public. To make them accessible from the web, you should create a symbolic link from public/storage to storage/app/public.
Laravel Docs - Filesystem - Configuration
If you do this, you will have a folder in public that you can use and point your URLs to these files. (www.yoursite.com/storage/...)

Related

View files inside storage folder for authenticated User

I am using spatie library to upload some files which will be saved to the storage folder. What I want to accomplished at the moment, is to view those files or images when I am an authenticated user. I've tried creating a symlink using this command ,
php artisan storage:link
But this makes those file to be seen publicly. What I only want is to view those file, only when the user is an authenticated user. So far this is what I did but it seems like I miss something.
ROUTE :
Route::get('/storage/{filePath}', 'ComplaintsController#fileStorageServe')->where(['filePath' => '.*'])->name('complaints.viewfile');
CONTROLLER :
public function fileStorageServe($file) {
// know you can have a mapping so you dont keep the sme names as in local (you can not precsise the same structor as the storage, you can do anything)
// any permission handling or anything else
// we check for the existing of the file
if (!Storage::disk('local')->exists($filePath)){ // note that disk()->exists() expect a relative path, from your disk root path. so in our example we pass directly the path (/.../laravelProject/storage/app) is the default one (referenced with the helper storage_path('app')
abort('404'); // we redirect to 404 page if it doesn't exist
}
//file exist let serve it
// if there is parameters [you can change the files, depending on them. ex serving different content to different regions, or to mobile and desktop ...etc] // repetitive things can be handled through helpers [make helpers]
return response()->file(storage_path('app'.DIRECTORY_SEPARATOR.($filePath))); // the response()->file() will add the necessary headers in our place (no headers are needed to be provided for images (it's done automatically) expected hearder is of form => ['Content-Type' => 'image/png'];
// big note here don't use Storage::url() // it's not working correctly.
}
VIEW :
#foreach($complaint->attachments as $attachment)
{{ $attachment->file_name }}
#endforeach
When I click the link it will give me something like this.
http://127.0.0.1:8000/complaints.viewfile/http%3A%2F%2F127.0.0.1%3A8000%2Fstorage%2F3%2F60580fdeadc55_worship.jpg
Please help. Thank you...
You need to understand how files are served by a web server and how that interacts with a laravel application.
You likely have nginx or apache set up to serve files from the public folder of your laravel app. ie: /var/www/sites/laravel-site/public.
When an HTTP request is sent to your server, if your nginx or apache is configured to serve files like laravel-site.com/storage/documents/secrets.pdf statically, then your laravel application code will never even be run, and you cannot control access to these files at the application level.
If you want to setup access control to files, you will need to first ensure the requests are not going to be served statically, and second setup a route to serve the files after checking if the user/request has permission to access the file(s) you want to serve.
There are lots of other great answers and resources on how to do this.
Correct me if im wrong but isn't the easiest way to do that via system-settings ? Like you have different Users and you just put them in different groups that have different rights for folders/files.

Laravel 404 error while viewing image saved in public directory of laravel project

I created Laravel project and able to make it work to get json output as well. However image link in json is not working.
https://android.factory2homes.com/
json: https://android.factory2homes.com/index.php/api/products
image link:https://android.factory2homes.com/index.php/public/12142.jpg
i tried creating symlink and copied same image in storage folder as well, but not able to make it work.
The public folder in a Laravel project is basically the root folder that shows up on the website URL.
For security issues, you really don't want the users to have the ability to write anything directly on the public folder, because if you are not careful they could overwrite your php scripts and have them do whatever they want.
So generaly speaking you create a simlink inside the public folder to the storage folder that is outside the public directory. Laravel has even a built in artisan command to do that exactly which is:
php artisan storage:link
The URL to any image stored in that folder would be in your example:
https://android.factory2homes.com/storage/12142.jpg
You do not have to put any .php file, or public or anything else.
if the image is inside public then I don't think you need to give the url like index.php/public/someimage.jpg you can just do www.yousiteurl.com/someinage.jpg
I resolved issue by savings images to Public_html folder instead of public folder in Laravel app root folder. Public_html is the path that is visible to public, hence other solutions weren't working.

How to Download File from AWS S3 with Laravel Storage and delete it after

I am reworking Laravel Storage driver to work with Amazon S3 instead of local. All good so far.
The problem is that I can't use storage_path anymore (I think so)
I find out problem with code where I want:
Create file (pdf e.g.) (All good here)
Show response that file has been created successfully. (All good here)
Redirect to another URL, where I check if File exists. (All good here)
If File exists Download (All good here)
Delete after Download (Don't know how)
Working code before S3:
return response()->download(storage_path('app/folder/'.$path.'/'.$filename), $filename)->deleteFileAfterSend(true);
Attempt (Working without delete):
return Storage::download('folder/'.$path.'/'.$filename, $filename);
Attempts (Not working if want to delete):
return Storage::download('folder/'.$path.'/'.$filename, $filename)->deleteFileAfterSend(true);
return Storage::download('folder/'.$path.'/'.$filename, $filename)->delete('app/folder/'.$path.'/'.$filename, $filename);
return response()->download(Storage::get('folder/'.$path.'/'.$filename), $filename)->deleteFileAfterSend(true);
Storage driver is "s3" with root 'app' thats why is missing in Storage::driver('s3) ....
Have no idea is there anyway to rework the code to working in this sequence. Or Have to totally rework the idea of the create->download->deleteAfter?

Where should my users folder be in a Slim 3 project?

I'm currently building a simply file hosting script using Slim 3. Currently I have my users folder on the same level as my public directory. Now that I'm attempting to access the files inside the user folder I'm getting errors caused by my document root not being able to access my users folder. Would it be a better idea to put my users folder inside my public folder because technically that would be public info to the logged in user?
It depends on what these files are - If they are only for the specific user or if they are available to all users.
When the files has to be private you can not put them into public, simple because everyone could hack url and get access to them. So you should put them in any data directory and make them available using an endpoint like /file/{username}/{name}.
In such endpoint you can easily append Header about filetype or if it should download or try to show in the browser window.
Whatever you make publicly available to the web server will be handled by default as any other asset:
Its URL is based upon the actual file name
If you know the URL you can download it
If it's a .php file it will be executed
You can certainly address all this concerns (and some of them may not even be concerns for your use case) but I don't think this is the ideal layout for a typical user-managed directory tree. Your current approach makes more sense to me.
To access such files you need to create a proper download script that makes all the appropriate checks (e.g. access checks), matches file system stuff from URLs and serves the assets as static files. In Slim that means creating a route with parameters and writing a handler function that does all this stuff.

Laravel: saving images in app public folder

How do you think I should organize images storage in my Laravel app? For example, I have a self-build admin panel and Articles module. Every article can have image that I should upload from Article's edit page in admin panel. So this image should be accessible through, for example, /images/somehash.jpg. But I can't give app privileges to write in public folder for security reasons. What variants of resolving this problem I have?
Create private folder e.g. {app_root}/storage/images, create route that handles URL /images/*, read image from storage and return it;
Maybe some workarounds with .htaccess;
You variant(s)?
Thanks!
If you don't want to store the images in public directory, then create storage/app/images directory and store the images in it.
Depending on your application's requirements, you may or may not need to create routes to read these images.
Whether you save your images in your public folder or a private folder, depends on your logic. When you upload your files in a public folder then those files can be downloaded directly from the web server without starting the
Laravel application. But if you choose to store your files in a private folder then those files are private and the requester has to get those files from your Laravel application. So if your files are open to everybody(like CSS or JS files) then that means you can put them in a public folder. But if for any reason your files have any kind of restriction or any validation that needs to be checked before letting the users to access that file, then you can upload those files in a private folder.

Categories