Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Setup a Laravel Storage driver with Google Drive API

Setup a Laravel Storage driver with Google Drive API

Log in to your Google Account and go to this website:

https://console.developers.google.com/

Getting your Client ID and Client Secret

Create a new project using the dropdown at the top.

Create a new project

After you enter a name, it takes a few seconds before the project is successfully created on the server.

Make sure you have the project selected at the top.

Then go to Library and click on "Drive API" under "Google Apps APIs".

Find Google Drive API

And then Enable it.

Enable Google Drive API

Then, go to "Credentials" and click on the tab "OAuth Consent Screen". Fill in a "Product name shown to users" and Save it. Don't worry about the other fields.

Consent Screen

Then go back to Credentials, click the button that says "Create Credentials" and select "OAuth Client ID".

Create Credentials

Choose "Web Application" and give it a name.

Enter your "Authorized redirect URIs", preferably your test URL (http://mysite.dev) and your production URL (https://mysite.com) - or create a separate production key later. Also add https://developers.google.com/oauthplayground temporarily, because you will need to use that in the next step.

Credentials

Click Create and take note of your Client ID and Client Secret.

Getting your Refresh Token

Now head to https://developers.google.com/oauthplayground.

Make sure you added this URL to your Authorized redirect URIs in the previous step.

In the top right corner, click the settings icon, check "Use your own OAuth credentials" and paste your Client ID and Client Secret.

Use your own OAuth credentials

In step 1 on the left, scroll to "Drive API v3", expand it and check each of the scopes.

Check Scopes

Click "Authorize APIs" and allow access to your account when prompted.

When you get to step 2, check "Auto-refresh the token before it expires" and click "Exchange authorization code for tokens".

Exchange authorization code for tokens

When you get to step 3, click on step 2 again and you should see your refresh token.

Refresh Token

Getting your Folder ID

If you want to store files in your Google Drive root directory, then the folder ID can be null. Else go into your Drive and create a folder.

Because Google Drive allows for duplicate names, it identifies each file and folder with a unique ID. If you open your folder, you will see the Folder ID in the URL.

Folder ID

Install in Laravel

Pull in Flysystem Adapter for Google Drive:

composer require nao-pon/flysystem-google-drive:~1.1

Add the storage disk configuration to config/filesystem.php:

return [
  
    // ...
  
    'cloud' => 'google', // Optional: set Google Drive as default cloud storage
    
    'disks' => [
        
        // ...
        
        'google' => [
            'driver' => 'google',
            'clientId' => env('GOOGLE_DRIVE_CLIENT_ID'),
            'clientSecret' => env('GOOGLE_DRIVE_CLIENT_SECRET'),
            'refreshToken' => env('GOOGLE_DRIVE_REFRESH_TOKEN'),
            'folderId' => env('GOOGLE_DRIVE_FOLDER_ID'),
        ],
        
        // ...
        
    ],
    
    // ...
];

And update your .env file:

GOOGLE_DRIVE_CLIENT_ID=xxx.apps.googleusercontent.com
GOOGLE_DRIVE_CLIENT_SECRET=xxx
GOOGLE_DRIVE_REFRESH_TOKEN=xxx
GOOGLE_DRIVE_FOLDER_ID=null

Save GoogleDriveServiceProvider.php to app/Providers and add it to the providers array in config/app.php:

App\Providers\GoogleDriveServiceProvider::class,

Test Drive

Now you should be up and running:

Route::get('test', function() {
    Storage::disk('google')->put('test.txt', 'Hello World');
});
<?php
namespace App\Providers;
use Illuminate\Support\ServiceProvider;
class GoogleDriveServiceProvider extends ServiceProvider
{
/**
* Bootstrap the application services.
*
* @return void
*/
public function boot()
{
\Storage::extend('google', function($app, $config) {
$client = new \Google_Client();
$client->setClientId($config['clientId']);
$client->setClientSecret($config['clientSecret']);
$client->refreshToken($config['refreshToken']);
$service = new \Google_Service_Drive($client);
$adapter = new \Hypweb\Flysystem\GoogleDrive\GoogleDriveAdapter($service, $config['folderId']);
return new \League\Flysystem\Filesystem($adapter);
});
}
/**
* Register the application services.
*
* @return void
*/
public function register()
{
//
}
}
@netwons
Copy link

netwons commented Dec 14, 2020

@Jangbe
okey

@netwons
Copy link

netwons commented Dec 15, 2020

@Jangbe
Now how to import the desired file into Google doc?

@Jangbe
Copy link

Jangbe commented Dec 16, 2020

@Jangbe
Now how to import the desired file into Google doc?

I don't know, I've never tried it

@amirkhan402
Copy link

amirkhan402 commented Feb 5, 2021

Google\Service\Exception
{ "error":
{ "errors": [ {
"domain": "global", "reason": "required", "message": "Login Required", "locationType": "header", "location": "Authorization" } ],
"code": 401,
"message": "Login Required" }
}

Facing this issue, anyone facing the similar issue? how can I get rid of this thing

@tarzanking
Copy link

tarzanking commented Feb 6, 2021

Hi, I have successfully integrated with the API but each time upload it to create a new file with the same name cant be overwritten. Anyway to overwrite the existing file without deleting it?

    `Storage::disk('public')->put('products.json', json_encode($response));`

image

@wgerro
Copy link

wgerro commented Feb 19, 2021

AWS S3 > Google Cloud Storage

@Roar1827
Copy link

Roar1827 commented Mar 10, 2021

Anyone getting the 401 login required error: double check that when you copy/pasted your client ID that it didn't add a trailing slash on you.

@myazidinniam
Copy link

myazidinniam commented Mar 18, 2021

{\n
"error": {\n
"errors": [\n
{\n
"domain": "global",\n
"reason": "required",\n
"message": "Login Required",\n
"locationType": "header",\n
"location": "Authorization"\n
}\n
],\n
"code": 401,\n
"message": "Login Required"\n
}\n
}\n

you can change env file on section GOOGLE_REFRESH_TOKEN add delimiter double quote for value inside

GOOGLE_REFRESH_TOKEN="1//04xd08cKBcYDWCgYIARAAGAQSNwF-L9IruTrG9cNMQajASodNAnuoYRPsPWpbJ9QFwzBPP_ny9nB8_xxxxxxxxxx"

this is work for me

@myazidinniam
Copy link

myazidinniam commented Mar 18, 2021

Google\Service\Exception
{ "error":
{ "errors": [ {
"domain": "global", "reason": "required", "message": "Login Required", "locationType": "header", "location": "Authorization" } ],
"code": 401,
"message": "Login Required" }
}

Facing this issue, anyone facing the similar issue? how can I get rid of this thing

you can change env file on section GOOGLE_REFRESH_TOKEN add delimiter double quote for value inside

GOOGLE_REFRESH_TOKEN="1//04xd08cKBcYDWCgYIARAAGAQSNwF-L9IruTrG9cNMQajASodNAnuoYRPsPWpbJ9QFwzBPP_ny9nB8_xxxxxxxxxx"

this is work for me

@paulcedo
Copy link

paulcedo commented Apr 14, 2021

Hi, may i know why our refresh token expired every week? any suggestion? we already checked the Auto refresh before it expires

@swamyyadav
Copy link

swamyyadav commented Apr 16, 2021

refresh token expired every week, even after selecting the "Auto-refresh the token before it expires" check box, Kindly help on this.
THANKS IN ADVANCE.

Copy link

ghost commented Apr 16, 2021

refresh token expired every week, even after selecting the "Auto-refresh the token before it expires" check box, Kindly help on this.
THANKS IN ADVANCE.

Follow the tutorial step step by step given above. Me too using the same and never got any token errors.

@SendraIlhamMandala
Copy link

SendraIlhamMandala commented Apr 21, 2021

if ($this->image) {
return Storage::disk('google')->url('1RJ_GfF69LlD-H51Tjj4YW_hfLDzlylnk'.$this->image);
// return $image;
} else {
return asset('img/no-image-default.png');
}
this my code in model to get img

I had the same problem, but there is no need to use asset function.
1.You should first get the path of the file by the following code, it will returns you an array,Which you can find the path from:
Storage::cloud()->listContents(<folder_path>);
or
Storage::disk('google')->listContents(<folder_path>);

2.Then you should create a route that returns the file as follows:
Route::get(<your_path>, function(){
return Storage::cloud()->response(<file_path>);
});

  1. You can add the above path to the image source.

thank you very much !! this works

@nurpuji97
Copy link

nurpuji97 commented Jun 17, 2021

Error Otorisasi
Error 403: access_denied
The developer hasn’t given you access to this app. It’s currently being tested and it hasn’t been verified by Google. If you think you should have access

@erwinpratama
Copy link

erwinpratama commented Jun 19, 2021

Thank you. I will try soon.

@faizankhalil007
Copy link

faizankhalil007 commented Jun 22, 2021

Hi, Is there anyone facing the problem of limited files? I'm getting only 500 records although I have more than 45,000 files in my google drive directory?
Can anyone please let me know why I'm getting this

@afagard
Copy link

afagard commented Jun 29, 2021

Hi, Is there anyone facing the problem of limited files? I'm getting only 500 records although I have more than 45,000 files in my google drive directory?
Can anyone please let me know why I'm getting this

I believe it is due to Google Drive API limitations, you can only have so many results in a single request. This is pretty standard across all of Google's API's. I'm not sure it is something you can easily override.

That being said, if you have 45k files, chances are your server would run out of memory before being able to do anything with the array of data. Suggest processing in chunks.

@swamyyadav
Copy link

swamyyadav commented Jul 13, 2021

try to write this..
$content = $request->file('name')->getContent();
Storage::disk(google)->put('example.jpg', $content)

Hi, This not working for me[ got bad method], i tried differently for laravel 5.2

Storage::disk('google')->put('filename.jpg', fopen($request->file('name'),'r+'), 'public'); //source : i have researched ref code

above line worked for me,

@valiantboymaksud
Copy link

valiantboymaksud commented Oct 1, 2021

can I save the file from the drive to the server storage?

@netwons
Copy link

netwons commented Oct 29, 2021

yes

@jakecausier
Copy link

jakecausier commented Nov 1, 2021

Unfortunately the refresh token expires after 30 or so days and required a new one to be generated, even with the "Auto-refresh the token" checkbox enabled. It returns a 403 code.
Any idea on how to bypass this?

@jrnbulu
Copy link

jrnbulu commented Dec 5, 2021

Stuck with below details. Any help!!!
Google\Service\Exception: {
"error": {
"errors": [
{
"domain": "global",
"reason": "required",
"message": "Login Required",
"locationType": "header",
"location": "Authorization"
}
],
"code": 401,
"message": "Login Required"
}
}

  1. used secret and refresh token with double quote in .env file.
  2. Required configuration done at Google side
  3. calling Storage::cloud()->put("abc.png", $itemimage->imagedata); from a service file directly.
  4. code for GoogleDriveServiceProvider
setClientId($config['clientId']); $client->setClientSecret($config['clientSecret']); $client->refreshToken($config['refreshToken']); $service = new \Google_Service_Drive($client); $adapter = new \Hypweb\Flysystem\GoogleDrive\GoogleDriveAdapter($service, $config['folderId']); return new \League\Flysystem\Filesystem($adapter); }); } /** * Register the application services. * * @return void */ public function register() { // } } 5. app.php and filesystem.php required changes done.

@ChristianJAYs
Copy link

ChristianJAYs commented Dec 13, 2021

I am getting an error of: "ErrorException Undefined index:" on the "app\Providers\GoogleDriveServiceProvider." which is the Client ID. Does anyone knows how to solve this? Thank you

Copy link

ghost commented Dec 15, 2021

@ChristianJAYs It will me more clear If you can show your "app\Providers\GoogleDriveServiceProvider." file.

@ptucky
Copy link

ptucky commented Jan 7, 2022

Cool Thanks for this guide. Save my life ^_^

@akhmadgozali
Copy link

akhmadgozali commented Feb 7, 2022

how to make token never expires?

@ankur377
Copy link

ankur377 commented Feb 14, 2022

How to solve this eror
Failed to connect to oauth2.googleapis.com port 443: Timed out

@netwons
Copy link

netwons commented Jun 4, 2022

okey

@jocelinkisenga
Copy link

jocelinkisenga commented Jul 12, 2022

Is this package working in laravel 9?

@Jangbe
Copy link

Jangbe commented Jul 12, 2022

Is this package working in laravel 9?

I think this package is no longer supported for laravel 9, see this package instead Link

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment