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

Get started with Google Drive and Laravel

This gist has moved!

This gist was getting a lot of comments/questions, but since there are no notifications when someone replies to a gist, I've moved the setup instructions and a bunch of sample code to a dedicated Github repo.

https://github.com/ivanvermeyen/laravel-google-drive-demo

API key walkthrough

Step by step instructions on how to get the various keys needed to work with Google Drive can be found on the Github repo as well:

https://github.com/ivanvermeyen/laravel-google-drive-demo/blob/master/README.md#create-your-google-drive-api-keys

Find examples

Take a look at the commit history to get a quick overview of the demo code I've been adding:

https://github.com/ivanvermeyen/laravel-google-drive-demo/commits/master

Got questions?

If you have questions or comments, please create an issue on the Github repo. This is easier to follow up and enables others to find the answers as well.

https://github.com/ivanvermeyen/laravel-google-drive-demo/issues

@bkstar123

This comment has been minimized.

Copy link

bkstar123 commented Mar 31, 2017

Thank you for your great guideline. It is very clear & concise and work for me

@sergomet

This comment has been minimized.

Copy link

sergomet commented Apr 1, 2017

Thanks! it works great.
It's there a way, to get the file id from google drive after upload ?

@thinhclubn1

This comment has been minimized.

Copy link

thinhclubn1 commented Apr 2, 2017

great

@thinhclubn1

This comment has been minimized.

Copy link

thinhclubn1 commented Apr 2, 2017

pls, help me!
FatalErrorException in GoogleDriveServiceProvider.php line 15:
Class 'Google_Client' not found

@mmeyer2k

This comment has been minimized.

Copy link

mmeyer2k commented Apr 5, 2017

I am able to write files but I get file not found when using get(). Anyone else have this issue?

@elmage

This comment has been minimized.

Copy link

elmage commented Apr 22, 2017

I have the same issue using get(), Except i manually pass the file ID to the get method, then it returns file contents. I think files are retrieved with ID not file names because multiple files can have the same name.

@indrakaw

This comment has been minimized.

Copy link

indrakaw commented May 22, 2017

Help. I'm getting this error when I was following this step:

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

https://i.snag.gy/kwG7yR.jpg

What should I do?

@ivanvermeyen

This comment has been minimized.

Copy link
Owner Author

ivanvermeyen commented Jun 7, 2017

Hi, sorry for the delayed answer, it seems I don't get notified when someone leaves a reply here.

@sergomet @mmeyer2k @elmage You need to get files by their ID indeed, because filenames are not necessarily unique in Google Drive. There's more info on getting files in this issue: nao-pon/flysystem-google-drive#10

@thinhclubn1 Did you composer require nao-pon/flysystem-google-drive:~1.1 ?

@indrakaw Did you also add the oauthplayground url to the redirect url's?

@ghost

This comment has been minimized.

Copy link

ghost commented Jun 22, 2017

Hi Ivanv,

your work seems perfect.
We are using, October Cms, a laravel based cms to manage our websites.
We create a plugin to import docs file to october. Now we'd like to extend our plugin:
https://github.com/CitrinoDeveloping/oc-htmlToOctober/

We need the upload button connect and browser directly to a google drive user and folder.
Can you suggest an easy way to integrate it?

Another thing, if you know.
We need to execute a google script inside a laravel/october backend application.
Is it possible, what do you think?

Bye
Citrino

@ivanvermeyen

This comment has been minimized.

Copy link
Owner Author

ivanvermeyen commented Jun 22, 2017

@CitrinoDeveloping

I guess that if you want to dynamically access Google Drive per user, you will need to request a client id, secret and refresh token from each user... There should be other packages to make this process easier. Maybe even Laravel Sociallite, but I'm not sure...

Once you have these credentials, you can use the Google Drive API to upload a file:

\Storage::disk('google')->put('test.txt', 'Hello World');

Or to list files:

$dir = '/';
$recursive = false;
$files = \Storage::drive('google')->listContents($dir, $recursive);

Or to get a specific file:

$rawData = \Storage::disk('google')->get($fileId);

I haven't used Google Drive that intense, but you can check the adapter source to see what other methods you can use to manipulate the filesystem: https://github.com/nao-pon/flysystem-google-drive/blob/master/src/GoogleDriveAdapter.php

I hope this helps...

@ghost

This comment has been minimized.

Copy link

ghost commented Jun 26, 2017

Hi Ivan,

thanks for your suggestions. I have to connect to google drive with one user to a specific directory.
I tihnk it is possible also to create a parameter for the user and folder and pass all of them via gui.

We will update.

Bye

@anis1011

This comment has been minimized.

Copy link

anis1011 commented Jul 6, 2017

Help. I'm getting this error when I was following this step:
Click "Authorize APIs" and allow access to your account when prompted.

clientid
what should I do?
please Help me

@hoangquannit

This comment has been minimized.

Copy link

hoangquannit commented Jul 10, 2017

Hi Ivan,
I've checked all of the scopes, but it same error's @anis1011. Please help !

@mattCreative

This comment has been minimized.

Copy link

mattCreative commented Jul 12, 2017

Hey Ivan,
I am getting same error as @hoangquannit, and @anis1011.

EDIT
Looks like the redirect_uri had a backslash after it, I added another entry without the backslash and it got rid of the redirect_uri issue.

@1dnmr

This comment has been minimized.

Copy link

1dnmr commented Jul 19, 2017

Hi @ivanvermeyen,

tried on several accounts. Always get error:
400. That’s an error.

Error: invalid_scope

You don't have permission to access some scopes. Your project is trying to access scopes that need to go through the verification process. {invalid = [https://www.googleapis.com/auth/drive,https://www.googleapis.com/auth/drive.readonly,https://www.googleapis.com/auth/drive.metadata.readonly,https://www.googleapis.com/auth/drive.scripts,https://www.googleapis.com/auth/drive.metadata,https://www.googleapis.com/auth/drive.photos.readonly]} If you need to use one of these scopes, submit a verification request.


I added https://developers.google.com/oauthplayground (without backslash) and did everything you recommended. Not work(
Any ideas?

Update: somehow it fixed. I don't know exactly. May be just need time passed. Also I setup some Drive UI integration page.

@1dnmr

This comment has been minimized.

Copy link

1dnmr commented Jul 19, 2017

@ivanvermeyen,
New issue, after finishing all steps got error when call 'test' route which should create a file:

(1/1) Google_Service_Exception
{
"error": {
"errors": [
{
"domain": "global",
"reason": "required",
"message": "Login Required",
"locationType": "header",
"location": "Authorization"
}
],
"code": 401,
"message": "Login Required"
}
}

ClientId, Secret, Refresh token are set correctly

@ivanvermeyen

This comment has been minimized.

Copy link
Owner Author

ivanvermeyen commented Jul 21, 2017

Hey all,

I have updated the walkthrough slightly.
It seems to be working when you only enable the first Drive scope and not all of them.
After going to a few warning screen when allowing access to my account, I was able to get the refresh token from the playground.

dbcd6106-e56c-11e6-8340-bca54ee8f2b6

I've set up up a demo project with some sample code, available on GitHub:

https://github.com/ivanvermeyen/laravel-google-drive-demo

Maybe create new issues there.

@DannyAndres

This comment has been minimized.

Copy link

DannyAndres commented Jul 24, 2017

hey, great work! but i have an issue to save files on folders, how can i do that?.... i can't simply pass the folder's name, for example
Storage::cloud()->put('folderName/fileName.extension', File::get($file));
this does not work....

pd: i think this solves the problem
IDfolder, is the folder that i want to save things
Storage::cloud()->put('IDfolder/folderName/fileName.extension', File::get($file));

@ivanvermeyen

This comment has been minimized.

Copy link
Owner Author

ivanvermeyen commented Jul 24, 2017

Hey, I think the main problem with Google Drive is that file and folder names are not unique.
So you must use the ID (path) instead of the name...
This makes it a bit complicated to work with the filesystem, since you need to get the ID every time.

Check this demo code I've just added:
https://github.com/ivanvermeyen/laravel-google-drive-demo/blob/master/routes/web.php#L54-L75

@agbeterseer

This comment has been minimized.

Copy link

agbeterseer commented Jul 25, 2017

hey ivanvermeyen, doing a great job man. i have and issue here, am able to upload files to google drive but i also want to save the path to my Mysql DB. how can i achieve this.

this uploads the file to google drive but the path saved to my DB is from my local serve.
so how can get the path of the stored file on Google Drive.
//get the file name getClientOriginalName
$fileName = $file->getClientOriginalName();
$destinationPath = config('fileDestinationPath').'/'.$fileName;

     $uploaded = Storage::cloud()->put($destinationPath, file_get_contents($file->getRealPath()));

    if ($uploaded) {
    //create new object
    $indocument = new Document;

    //get input and store into variables set all input to insert to db
    $indocument->candidates_name = $request->candidates_name;
    $indocument->years_of_experience = $request->years_of_experience;
    $indocument->city_id = $request->location;
    $indocument->save();


    if ($indocument) {
       
    $indocument = Document::find($indocument->id);
    $indocument->cv_file=$destinationPath;
    $indocument->save();
    
    }
@ivanvermeyen

This comment has been minimized.

Copy link
Owner Author

ivanvermeyen commented Jul 25, 2017

I don't think there is any easy way to get a reference to a file when it is uploaded.

The way I would do it is upload the file, then get a fresh file listing, order by the timestamp and get the latest file that has that name...
If you have lots of simultaneous uploads and someone else uploads a file with the same name at the same time, you could get a reference to the wrong file... but I think those chances are minimal?

This would look something like this:
https://github.com/ivanvermeyen/laravel-google-drive-demo/blob/master/routes/web.php#L77-L93

@agbeterseer

This comment has been minimized.

Copy link

agbeterseer commented Jul 25, 2017

I modified your code and i was able to get the reference file i uploaded Google drive to my database

thanks very much.

$fileName = $file->getClientOriginalName();
$dir = '/';
$recursive = false; // Get subdirectories also?
$contents = collect(Storage::cloud()->listContents($dir, $recursive));
$dir = $contents->where('type', '=', 'dir')->first();
if ( ! $dir) {
return 'Directory does not exist!';
}
$pathName = $dir['path'].$fileName;
$uploaded = Storage::cloud()->put($pathName, file_get_contents($file->getRealPath()));
if ($uploaded) {
//create new object
$indocument = new Document;
//get input and store into variables set all input to insert to db
$indocument->candidates_name = $request->candidates_name;
$indocument->years_of_experience = $request->years_of_experience;
$indocument->city_id = $request->location;
$indocument->save();

    // dd($destinationPath);
    if ($indocument) {
    $indocument = Document::find($indocument->id);
    $indocument->cv_file=$pathName;
    $indocument->save();
    
    }
@ivanvermeyen

This comment has been minimized.

Copy link
Owner Author

ivanvermeyen commented Jul 25, 2017

This is good to store the file:

$pathName = $dir['path'].$fileName;

But don't you need the path of the uploaded file to save it in the database?
Now $fileName is still the original file name?

I'm thinking about writing some kind of wrapper class to work with the Google Drive file system with its ID's and duplicate names...

@agbeterseer

This comment has been minimized.

Copy link

agbeterseer commented Jul 25, 2017

Yes, that would nice
and i do need the path to save to database.
for now i just have the fileName and directory/fileName stored in the db.

i am uploading files of type doc, docx, pdf, and txt.

Now is there a way to render a word file open on the browser from laravel application when i view all ?

remember these files will be loading from Google Drive

@ivanvermeyen

This comment has been minimized.

Copy link
Owner Author

ivanvermeyen commented Jul 26, 2017

There seem to be packages that enable you to create/edit Word files, but I'm not sure if you can show the contents on a webpage... Wouldn't you need to convert it to HTML or something? Seems a bit weird to me.

You can let people download the Word file though:

$rawData = Storage::cloud()->get($filePath);

return response($rawData, 200)
    ->header('ContentType','application/vnd.openxmlformats-officedocument.wordprocessingml.document')
    ->header('Content-Disposition', 'attachment; filename="download.docx');
@guilhermeof

This comment has been minimized.

Copy link

guilhermeof commented Jul 27, 2017

Good afternoon,
How do I get the url to download the file?

@ivanvermeyen

This comment has been minimized.

Copy link
Owner Author

ivanvermeyen commented Jul 27, 2017

@guilhermeof I don't know if you can get a direct link to a file... The file would also need to be publicly shared etc...

But you can generate a link on your own website and let people download the file from your site directly.

When you list the contents of Google Drive, it returns an array.
Each array item is also an array, containing file or folder info, including a path.
If you get this path, you will get the raw file data, which you can use to force a download (see my previous reply).

To see some sample code on how to get the raw data, check this out:
https://github.com/ivanvermeyen/laravel-google-drive-demo/blob/master/routes/web.php#L77-L93

@Brabas

This comment has been minimized.

Copy link

Brabas commented Aug 8, 2017

Hi, Thank you for your great work.

Want to download a folder with its contents, I modified the following function in web.php

Route::get('get', function() {

  $filename = 'appply';        //name of folder

  $dir = '/';
  $recursive = false; // Get subdirectories also?
  $contents = collect(Storage::cloud()->listContents($dir, $recursive));

  $file = $contents
      ->where('type', '=', 'dir')
      ->where('filename', '=', pathinfo($filename, PATHINFO_FILENAME))
      ->where('extension', '=', pathinfo($filename, PATHINFO_EXTENSION))
      ->first(); // there can be duplicate file names!

  $rawData = `Storage::cloud()->get($file['path']);

  return response($rawData, 200)
      ->header('ContentType', $file['mimetype'])
      ->header('Content-Disposition', "attachment; filename='$filename'");
});

But I'm throwing the following error

(1/1) Google_Service_Exception
{
"error": {
"errors": [
{
"domain": "global",
"reason": "fileNotDownloadable",
"message": "Only files with binary content can be downloaded. Use Export with Google Docs files.",
"locationType": "parameter",
"location": "alt"
}
],
"code": 403,
"message": "Only files with binary content can be downloaded. Use Export with Google Docs files."
}
}

I try to call the method according to the documentation of the api,

rawData = Storage::cloud()->export($file['path'], 'application/vnd.google-apps.folder');

But it seems to me that I do not do it in the right place.

(1/1) BadMethodCallException
 Call to undefined method League\Flysystem\Filesystem::export

Could you guide me in what class should I modify to make it work?

@ivanvermeyen

This comment has been minimized.

Copy link
Owner Author

ivanvermeyen commented Aug 8, 2017

@Brabas if I understand it correctly, you are trying to download all files in the appply folder?

I don't think you can download a whole folder at once in a browser, but instead you can download each file individually.
So first get all files inside the folder, and then loop over the contents (files) and download them one by one...

If you want the end user to only need to download a single item, maybe you can save the files on the server and create a zip file or something? There's probably a package for that... Or you can just generate a download link for each file, because I don't think you can download multiple files in a single request...

Take a look at this sample code I just wrote...

Test Dir would then become appply.
I did assume that the appply folder is in the root of your Google Drive, just to keep it simple.

Hope this helps...

@Brabas

This comment has been minimized.

Copy link

Brabas commented Aug 10, 2017

Thank you very much for the guidance

@Arman8852

This comment has been minimized.

Copy link

Arman8852 commented Sep 9, 2017

I am getting error while trying to upload file using this controller method:

$files = $request->file('files');

if($request->hasFile('files')){
foreach ($files as $file) {
$disk = Storage::disk('google'); //for local, Storage::disk('local);
$disk->put($name, fopen($file, 'r+'));

      }
             }

When I am trying to uplaod in local storage.It's working fine.
But in case of Google storage,I am getting this error:

(1/1) ErrorException
A non well formed numeric value encountered

in GoogleDriveAdapter.php (line 1143)
at HandleExceptions->handleError(8, 'A non well formed numeric value encountered', '/app/vendor/nao-pon/flysystem-google-drive/src/GoogleDriveAdapter.php', 1143, array('iniName' => 'memory_limit', 'val' => '128M', 'last' => 'm'))in GoogleDriveAdapter.php (line 1143)](url)

@mulqan

This comment has been minimized.

Copy link

mulqan commented Oct 18, 2017

hey, how can i upload image with this?

@nimshavb

This comment has been minimized.

Copy link

nimshavb commented Nov 10, 2017

I need service account integration with google drive access using laravel. Refresh token get expired within the time limit. Plz help

@Dimona

This comment has been minimized.

Copy link

Dimona commented Nov 10, 2017

Done all by your steps. Added all constants into .env and have the following problem on /list route

@szabizs

This comment has been minimized.

Copy link

szabizs commented Feb 7, 2018

@Dimona Did you manage to solve this problem?
I'm facing the exact same problem.

@ivanvermeyen

This comment has been minimized.

Copy link
Owner Author

ivanvermeyen commented Feb 23, 2018

Only on the /list route? Seems to be related to authentication... If no routes are working, double check the keys in .env and the filesystems.php config file.

If the problem persist, please create an issue on the GitHub repo. It's hard to keep track of Gist comments (no notifications).

https://github.com/ivanvermeyen/laravel-google-drive-demo

@MostafaRabia

This comment has been minimized.

Copy link

MostafaRabia commented Apr 22, 2018

hi, why it doesn't cache photos if i get it from url ?

@leduonggithub

This comment has been minimized.

Copy link

leduonggithub commented May 15, 2018

hi ivanvermeyen , please help me with my problem. when user click, choose file(s), then click submit, i want store this file(s) directly to google driver, and then save link to database. how can i do that

@npv34

This comment has been minimized.

Copy link

npv34 commented Jun 7, 2018

How to show image thumbnail image upload ???

@CarlosMarival

This comment has been minimized.

Copy link

CarlosMarival commented Jul 30, 2018

how can i get the others attributes like iconLink

@nutch31

This comment has been minimized.

Copy link

nutch31 commented Aug 3, 2018

Please advise how to get (teamDriveId) GOOGLE_DRIVE_TEAM_DRIVE_ID .
i need to more learn about this one.

Thank you for your advise .

@afrasiyabhaider

This comment has been minimized.

Copy link

afrasiyabhaider commented Oct 20, 2019

How to get downloadable link of a file?

@ivanvermeyen

This comment has been minimized.

Copy link
Owner Author

ivanvermeyen commented Oct 20, 2019

Hi,

Please create an issue @ https://github.com/ivanvermeyen/laravel-google-drive-demo for any questions.
This keeps it organized and helps other people to find an answer to similar problems.

Also, make sure you go through open and closed issues first, as your question may already have been asked/answered. 👍

I will be happy to help you out if I can!

https://github.com/ivanvermeyen/laravel-google-drive-demo

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.