Maximize Your Laravel App Performance with Public and Private Storage

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

  1. 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

  1. 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.

Go To Top