How to upload files to Google cloud storage from a Laravel application

How to upload files to Google cloud storage from a Laravel application

Utilizing Google cloud storage for file uploads and management from a laravel application

In this article, we'll be using Google cloud storage to manage file uploads from a laravel application.

Cloud Storage allows world-wide storage and retrieval of any amount of data at any time. You can use Cloud Storage for a range of scenarios including serving website content, storing data for archival and disaster recovery, or distributing large data objects to users via direct download.

Files are stored on buckets in Google cloud storage

Advantages of using cloud based digital asset management

  • File organization
  • Easily optimized
  • Makes application faster
  • Makes team collaboration easier
  • Minimize the risk of loosing media files

Let's start with a fresh laravel app

laravel new laravel_upload_using_google_cloud_storage

OR

composer create-project laravel/laravel_upload_using_google_cloud_storage

After successful installation change directory to laravel_upload_using_google_cloud_storage

cd laravel_upload_using_google_cloud_storage

image.png

Let's serve the application on port 8001 using the port flag

php artisan serve --port=8001

image.png

We'll use this article on Complete Laravel 8 Authentication Using Laravel Fortify and Bootstrap 4 to set up the application authentication.

For this tutorial - we''ll stop at the login and register section of the article mentioned above.

Next, Add an extra column to the users table

            $table->string('avatar')->nullable();

image.png

Next, set the environment variable for this application on the .env file

DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=laravel_upload_using_google_cloud_storage
DB_USERNAME=root
DB_PASSWORD=

Next, run the migration command

php artisan migrate

image.png

Next, create an upload controller to handle picture upload for users

php artisan make:controller UploadController

Add two methods to handle displaying file upload form and storing the data

    public function upload()
    {}

    public function store(Request $request)
    {}

Add the routing in the web.php file

Route::middleware(['auth'])->group(function () {
    Route::get('/home', [UploadController::class, 'upload'])->name('home');
    Route::post('uploads/store', [UploadController::class, 'store'])->name('uploads.store');
});

Next, create views for login, register and a form for uploading a profile picture

image.png

image.png

image.png

Views for this tutorial is available on this repository here

Next, create a new project in google console

Click on the new project button

image.png

Next enter the preferred details for the project

image.png

After creating the project the details are shown on the dashboard

Project info

Project name
Laravel upload

Project number
1549378xxxxx

Project ID
laravel-upload-98xxxx

Next, create a service account for this project to obtain the json file of the credentials

Click on the navigation and hover over the IAM $ Admin then click on the service accounts

image.png

Click on create service account to add a service account for the project created

image.png

Fill in the service account details

image.png

Click create and continue

Next, select the storage admin role and click on continue

image.png

If you want to grant users access you can do so here but it's optional

image.png

Click on Done

image.png

Next click on the service created and go to the keys tab section to access the download a json file

image.png

Click on create new

image.png

Then click on create and it'll automatically download the json file to your computer.

Please keep these json file or credentails confidential or git ignore the file from going to version control systems

Next, Let's move to Google cloud storage aspects

Click on [cloud storage] (cloud.google.com/storage/docs)

You can click on the storage option on the dashboard of the project

image.png

or use the navigation menu as shown in the image below then click on browser

image.png

Next, click on create bucket and fill in the details requested

image.png

Next

image.png

Next

You can select any region based on your choice but the multiple region is more expensive than the single region

image.png

Next

image.png

Next, choose the fine-grained option

Specify access to individual objects by using object-level permissions (ACLs) in addition to your bucket-level permissions (IAM). Read more about Access control list

image.png

Next, click on create

image.png

Awesome!!!

Next, create a folder laravel-upload to keep the content organized

image.png

Next, set the environment variable for cloud storage in the .env file


GOOGLE_CLOUD_PROJECT_ID=laravel_upload_using_google_cloud_storage
GOOGLE_CLOUD_STORAGE_BUCKET=laravel-upload-gcs

Next, move the downloaded json file to the config/ folder and also create googlecloud.php file under the same folder

  • config/googlecloud.php

This is what the googlecloud.php should look like

  • config/googlecloud.php
<?php

return [
    'project_id' => env('GOOGLE_CLOUD_PROJECT_ID'),
    'storage_bucket' => env('GOOGLE_CLOUD_STORAGE_BUCKET'),
];

Next, integrate the cloud-storage package

composer require google/cloud-storage

Next, run the commands below

composer dump-autoload

image.png

php artisan optimize:clear

image.png

Next, import the package on the controller in our case UploadController

use Google\Cloud\Storage\StorageClient;

image.png

Here's the store method for uploading the file to Google cloud storage

    public function store(Request $request)
    {

//validate the file upload
        $request->validate([
            'avatar' => 'required|image|max:10240',
        ]);

//get the authenticated user
        $user = Auth::user();

//get the credentials in the json file
        $googleConfigFile = file_get_contents(config_path('laravel-project.json'));

//create a StorageClient object
        $storage = new StorageClient([
            'keyFile' => json_decode($googleConfigFile, true)
        ]);

//get the bucket name from the env file
        $storageBucketName = config('googlecloud.storage_bucket');

//pass in the bucket name
        $bucket = $storage->bucket($storageBucketName);

        $avatar_request = $request->file('avatar');

        $image_path = $avatar_request->getRealPath();

//rename the file
        $avatar_name = $user->name.'-'.time().'.'.$avatar_request->extension();

//open the file using fopen
        $fileSource = fopen($image_path, 'r');

//specify the path to the folder and sub-folder where needed
        $googleCloudStoragePath = 'laravel-upload/' . $avatar_name;


//Delete previously uploaded image to cloud storage by this user
        if(Auth::user()->avatar !== ''){
            $object = $bucket->object('laravel-upload/'.Auth::user()->avatar );
            $object->delete();
        };

//upload the new file to google cloud storage 
        $bucket->upload($fileSource, [
            'predefinedAcl' => 'publicRead',
            'name' => $googleCloudStoragePath
        ]);

//pass in the name of the file and save
        $user->avatar = $avatar_name ;
        $user->save();

//return a success message to the user
        return redirect()->route('home')
                        ->with('success','Uploaded successfully.');
    }

//Same approach is applicable to PDF file uploads.

For more features check here

Next, add a getter for avatar in the user model to append the URL to the picture on cloud storage

//laravel 9
public function avatar(): Attribute
    {
        return new Attribute(
            get: fn ($value) => 'https://storage.googleapis.com/laravel-upload-gcs/laravel-upload/'.$value,
        );
    }

Next, refresh the browser click on home and upload a picture

Awesome!!! After uploading the file here's the output

image.png

On Google cloud storage

image.png

Article research credits

Thank you for reading this article.

Please kindly share with your network and feel free to use the comment section for questions, answers, and contributions.

Do you love this article?? please follow me on Hashnode alemsbaja or Twitter @alemsbaja to stay updated for more articles

Did you find this article valuable?

Support Alemoh Rapheal Baja by becoming a sponsor. Any amount is appreciated!