How to use Public and Local Storage in Laravel
Laravel, a popular PHP framework, offers an easy way to manage files and directories in your web application. Laravel provides various storage options out of which two are: public storage and local storage. Both storage options serve different purposes and can improve the performance of your Laravel app.
Public Storage
Public storage is accessible from the public and can be used to store files such as images, videos, and other assets that need to be served directly to the browser. Laravel stores these files in the public
directory and generates a public URL for each file, which can be accessed from anywhere.
Local Storage
Local storage, on the other hand, is meant for files that should not be publicly accessible. To use the local
storage, your file operations are relative to the root
directory specified in your filesystems
configuration file. These files are stored in the storage/app
directory and can only be accessed programmatically. Some examples of such files include user-uploaded files and sensitive information like configuration files.
Amazon S3 Compatible Filesystems
The default configuration file for your application’s filesystem
contains a disk configuration for the s3
disk. In addition to using this disk to interact with Amazon S3, you may use it to interact with any other S3-compatible file storage service, such as MinIO or DigitalOcean Spaces.
After updating the disk’s credentials to match those of the service you’re planning to use, you’ll usually just need to update the value of the endpoint
configuration option. This option’s value is typically set via the AWS_ENDPOINT
environment variable:
'endpoint' => env('AWS_ENDPOINT', 'https://minio:9000'),
How to Use Public Storage in Laravel
By default, the public storage uses the local storage, and stores its files in the storage/app/public directory. To make these files available on the web, you can create a symbolic link from public/storage
to storage/app/public
. Following this folder convention will help you keep all your publicly accessible files in a single directory.
To create the symbolic link, you may use the storage:link Artisan command:
php artisan storage:link
To use public storage in Laravel, you need to store your files in the public directory. You can do this by using the Storage
facade and the put
method :
In your controller use these classes for representing data as object:
use Illuminate\Support\Str;
use Illuminate\Support\Facades\File;
use Illuminate\Support\Facades\Storage;
In your controller use this function to upload file:
public function uploadFile(Request $request)
{
if ($request->file('user_image')) {
$file = $request->file('user_image');
$folderPath = 'users/images';
$filePath = $folderPath . "/" . Str::random(5) . "_" . time() . "." . $file->getClientOriginalExtension(); // set unique name users/images/vv82t_1675340672.png
Storage::disk('public')->put($filePath, File::get($file), 'public'); // to upload in public storage
$request->merge(['image' => $filePath]); // to store path in database
}
}
The above code will store the contents in the storage/app/public/users/images directory as vv82t_1675340672.png. To retrieve the URL of the file, you can use the URL method
<img src="{{ Storage::url('users/images/vv82t_1675340672.png') }}" >
How to Use Local Storage in Laravel
To use local storage in Laravel, you need to store your files in the storage/app
directory. You can do this by using the Storage
facade.
In your controller use this function to upload file:
public function uploadFile(Request $request)
{
if ($request->file('file')) {
$storeFilePath = $request->file('file')->store('users/files'); // to upload in storage/app/users/files Output: users/files/{randomstring.extention}
// You can also use Storage facade and the put method
// $filePath = "users/files". "/" . Str::random(5) . "_" . time() . "." . $request->file('file')->getClientOriginalExtension();
// Storage::disk('local')->put($filePath, File::get($request->file('file')));
$request->merge(['user_file' => $storeFilePath]); // to store path in database
}
}
The above code will store the contents in the storage/app/users/files directory as {randomstring.extention}. To retrieve the file from local storage is different from public storage
To download the file
- Add a route for access file:
Route::get('file/download/{file_name?}', 'Filestoragecontroller@filedownload')->name('file.download');
2. After successfully generated an FileStorageController please add this commands:
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Storage;
use Illuminate\Support\Facades\Auth;
use Response;
What we can do, is create a route that points to a Controller method and that method is responsible to do all the authentication/authorization needed before returning a download response, so the owner can get the file. Let’s see an example:
public function fileDownload($fileName)
{
// $fileName = 'report1253.pdf';
// We should do our authentication/authorization checks here
// We assume you have fileName in url with a defined belongs to User relationship.
if(Auth::user()) {
// filename should be a relative path inside storage/app to your file like 'users/files/report1253.pdf'
return Storage::download('users/files/'.$fileName);
// If you want to delete the file use below line
// Storage::delete('users/files/'.$fileName);
}else{
return abort('403');
}
}
In blade file simple way to create a link
<a href="{{ route('file.download', ['file_name' => $credits->document] ) }}" target="_blank" download>Download</a>
How to serve image on web
- Add a route for access file:
Route::get('file/serve/{file_name?}', 'Filestoragecontroller@fileserve')->name('file.serve');
2. After that we write the function as below in the body part of FileStorageController.
protected function fileServe($fileName)
{
//check image exist or not
$exists = Storage::disk('local')->exists('users/images'.$fileName);
if($exists) {
//get content of image
$content = Storage::get('users/images/'.$fileName);
//get mime type of image
$mime = Storage::mimeType('users/images/'.$fileName); //prepare response with image content and response code
$response = Response::make($content, 200); //set header
$response->header("Content-Type", $mime); // return response
return $response;
} else {
abort(404);
}
}
In blade file simple way to show image with route
<img src="{{ route('file.serve', ['file_name' => $user->image]) }}"></img>
// $user->image as user_image.jpg
Conclusion
Laravel provides two types of storage options: public storage and local storage. By using both storage options, you can improve the performance of your Laravel app and keep sensitive information secure. With the use of the Storage facade, it’s easy to implement both public and local storage in your Laravel app.