A Complete Guide to Laravel Storage
In modern web development, file uploads are one of the most commonly used features and Laravel Storage provides an intuitive way to handle the file storage.
In this guide, we will look at how Laravel has simplified the file uploads and managing file storage using Laravel Storage facade. If you are new to Laravel then this guide will walk you through the different aspects of file storage.
Playground Setup
To try the examples provided in this post will require an existing Laravel application or a new one. I will start with a new Laravel project and use the composer to create a new Laravel application.
composer create-project laravel/laravel DemoApp
Above command will generate a new Laravel application in a folder named DemoApp.
Open your command line terminal and move into the DemoApp folder. Now run the below command.
php artisan make:auth
This commmand will scaffold a bootstrap based template layout. Now open the welcome.blade.php file from resources/views
folder and replace all markup with the below one.
@extends('layouts.app') @section('content') <div class="container"> <div class="row justify-content-center"> <div class="col-md-8"> <div class="card"> <div class="card-header">Laravel Storage Example</div> <div class="card-body"> <form action="{{ route('upload') }}" method="POST" role="form" enctype="multipart/form-data"> @csrf <div class="form-group row"> <label for="file" class="col-md-4 col-form-label text-md-right">Select a file to upload</label> <div class="col-md-6"> <input id="file" type="file" class="form-control @error('file') is-invalid @enderror" name="file" value="{{ old('file') }}"> @error('file') <span class="invalid-feedback" role="alert"> <strong>{{ $message }}</strong> </span> @enderror </div> </div> <div class="form-group row mb-0"> <div class="col-md-8 offset-md-4"> <button type="submit" class="btn btn-primary">Upload File</button> </div> </div> </form> </div> </div> </div> </div> </div> @endsection
In this view, we have added a form with an input file field and a submit button to submit the form. The form in this view template is pointing a route named upload
, let’s add this route in our routes/web.php
file.
Route::post('/upload', 'HomeController@upload')->name('upload');
Next, we will add the upload()
method in the HomeController.
public function upload(Request $request) { // All code examples will go into this method }
Next, we need to update the middleware for this controller. Change the __construct()
method from this:
** * Create a new controller instance. * * @return void */ public function __construct() { $this->middleware('auth'); }
To this:
** * Create a new controller instance. * * @return void */ public function __construct() { $this->middleware('auth')->except('upload'); }
That’s all, now we have a form with a controller method where we can test all the examples regarding Laravel Storage. So let’s start.
How Laravel Storage Handles a File
Laravel is one of the fastest-growing frameworks due to its simplicity and flexibility. Therefore there are multiple options available to handle the file uploads and storage formats.
For example, you can use the local storage system where all the files will be stored within the project itself. You can also use the SFTP to transfer files to other servers or you can utilize the Cloud Storage for storing all your files. Laravel provides the Amazon S3 or Google Cloud storage out of the box.
In Laravel, we call all these storage types as disks, think of file storage and label it as a disk in Laravel. If you open the config/filesystems.php
file, you will find out all the available disks and their configurations.
In the config/filesystems.php
file, you will find out two types of disks named local and public. Laravel by default use the local disk, while you can specify the disk type you want to use when uploading the files.
In the public disk, you will find out that the root of this disk is set to storage/app/public
, since the Laravel’s root is in public folder, you have to link the storage/app/public
folder to Laravel’s public folder which is placed in the root of your project folder. You can achieve this by running the below artisan command.
php artisan storage:link
File Uploads in Laravel
Since, we have already setup the playground for practicing the file upload, let’s go ahead and write some code to upload files. In the upload()
method of HomeController add the below line of code:
public function upload(Request $request) { $path = $request->file('file')->store('files'); dd($path); }
In the above method, we get the file uploaded through the Laravel’s Request object and use the store()
method to store uploaded file in the files folder.
Now, if you run the application and upload a file using the form we created in the earlier section, your file will be uploaded and Laravel will dump the file path.
Now, if you go to storage/app
folder, you will find a new folder named files and uploaded will be available in this folder.
If you want to give a name to the file you are uploading, you can use storeAs()
method like below.
public function upload(Request $request) { $file = $request->file('file'); // Generate a file name with extension $fileName = 'profile-'.time().'.'.$file->getClientOriginalExtension(); // Save the file $path = $file->storeAs('files', $fileName); dd($path); }
After uploading a new file, you will get something like the following output.
"files/profile-1564586486.jpg"
Multiple File Uploads in Laravel
To upload multiple images at once, you have to adjust the file input field in your form. Change the input field from this:
<input id="file" type="file" class="form-control @error('file') is-invalid @enderror" name="file" value="{{ old('file') }}">
To this:
<input id="file" type="file" class="form-control @error('file') is-invalid @enderror" name="files[]" value="{{ old('file') }}" multiple>
We have changed the name of this input field from file
to files[]
and add the multiple attribute in it.
Now, we will store multiple images something like below:
public function upload(Request $request) { $paths = []; $files = $request->file('files'); foreach ($files as $file) { // Generate a file name with extension $fileName = 'profile-'.time().'.'.$file->getClientOriginalExtension(); // Save the file $paths[] = $file->storeAs('files', $fileName); } dd($paths); }
In the above method, we simply loop through all the files and save the path in the $paths
array.
If you upload now multiple files, you will get something like below output.
array:3 [▼ 0 => "files/profile-1564586818.jpg" 1 => "files/profile-1564586818.jpg" 2 => "files/profile-1564586818.jpg" ]
Validation Rules For Files Upload
For any web application, validation is one of the most important as you have to place some checks if a user is uploading the right file type, within the limit allowed and with correct dimensions if its an image file.
For our file uploads, we can add the validation rules right in our controller or you can use a Laravel Form Request.
public function upload(Request $request) { $validation = $request->validate([ 'file' => 'required|file|image|mimes:jpeg,png,gif,jpg|max:2048' ]); $file = $validation['file']; // Generate a file name with extension $fileName = 'profile-'.time().'.'.$file->getClientOriginalExtension(); // Save the file $path = $file->storeAs('files', $fileName); dd($path); }
In the above method, we added the validation that the uploaded file has to be a file and image with specified extension types and file should not be more than 2MB in size.
Useful Laravel Storage Facade Methods
Laravel Storage facade provides a convenient way to perform actions on the storage disks. For example, if you would like to specify which disk it should use when uploading a file, you do something like below.
Save File to a Specific Disk
Storage::disk('local')->put('filename.txt', 'File content goes here..');
Above code will create a filename.txt
file in local storage disk with the content provided.
Get Content of a File
To get the content of a file, you can use get()
method.
Storage::get('filename.txt');
Checking If a File Exists
To check if a file exist or not, we use the exists()
method available, which will return true
or false
value.
Append to a File
Use the below method of Storage facade to append to a file.
Storage::append('filename.txt', 'Append this text');
Prepend to a File
Use the below method of Storage facade to prepend to a file.
Storage::prepend('filename.txt', 'Append this text');
Download a File
To download a stored file from the storage disk use download()
method.
Storage::download('filename.txt');
Generating a Public URL
To generate a publicly available link for the file, use below method.
Storage::url('filename.txt');
Get Size of a File
To get the size of a file, use the below method.
Storage::size('filename.txt');
Delete a File
To delete a file, use delete()
method.
Storage::delete('filename.txt');
Learn More
You can find all the available method with their documentation here.
Working with Directories in Laravel Storage
Laravel Storage facade also provides a simple way to interact with the directories within your storage disks. Here we will look at some of the most common methods of Laravel Storage.
Get Files from a Directory
To get all files from a directory, we can use the files()
method on Laravel Storage facade.
Storage::files($directory);
If you want to get all files, from subdirectories of a directory, you can use allFiles()
method.
Storage::allFiles($directory);
Get All Directories within a Directory
To get a list of all directories from a given directory use the directories()
method.
Storage::directories($directory);
Just like files, you can use the allDirectories()
method to grab a list of all directories and sub-directories from a given directory.
Storage::allDirectories();
Create A Directory
Use the makeDirectory()
method to create a new directory.
Storage::makeDirectory($name);
Deleting a Directory
Use the deleteDirectory()
method to delete a particular directory.
Storage::deleteDirectory($name);
Learn More
You can learn more about managing directories on the Official Documentation of Laravel.
Using Amazon S3 Cloud Storage
In this section, we will look at how we can upload files on the Amazon S3 storage. Laravel provides the support for Amazon S3 out of the box, but we have to install a dependency package.
Open your terminal and run the below command in the root of your project folder.
composer require league/flysystem-aws-s3-v3 ~1.0
Once composer package installation finish, run the composer dump-autoload
.
Now, head to our upload()
method we created earlier where we will add the storage logic for our file upload.
To upload the files to Amazon S3, we will use the put()
method of the Laravel Storage facade.
Firstly, we will need to create an instance of the S3 using disk()
method of the Storage facade. Then we will supply, the relative path to your S3 bucket, the content of the file and the permission of the file.
public function upload(Request $request) { $validation = $request->validate([ 'file' => 'required|file|image|mimes:jpeg,png,gif,jpg|max:2048' ]); $file = $validation['file']; // Generate a file name with extension $fileName = 'profile-'.time().'.'.$file->getClientOriginalExtension(); // Save the file $s3 = Storage::disk('s3'); $filePath = '/uploads/media/' . $fileName; $s3->put($filePath, file_get_contents($file), 'public'); }
Remember to add the your API credentials in your .env
file which you can find in config/filesystems.php file.
's3' => [ 'driver' => 's3', 'key' => env('AWS_ACCESS_KEY_ID'), 'secret' => env('AWS_SECRET_ACCESS_KEY'), 'region' => env('AWS_DEFAULT_REGION'), 'bucket' => env('AWS_BUCKET'), 'url' => env('AWS_URL'), ],
Add the above enviornment variables in your .env
file to use the Amazon S3 storage.
Conclusion
Laravel Storage provides a very simple way to manage your storage. You can find more information on the Official Documentation of Laravel.
If you have any comments or suggestions to improve this post, let us know in the comments box below.