Recently, we were performing some work for a client. The client wanted us to showcase pictures of recent projects their company had completed. We use Google Workspace for our organization which means we use Google Drive. We wanted to give the client the ability to upload photos to a folder in our Google Drive and then have those images displayed on their website. We use AWS exclusively for hosting our client's websites and we also make use of Amazon S3 for storing all of our client's assets. So if the client uploads their pictures to Google Drive, and we use S3 to host our client asset files, we needed a way for the files to get from Google Drive to AWS.
We developed 2 ways of handling this task.
This blog will be focusing on #1 above, using a Laravel Scheduled Task.
We will be using the Google Drive v3 API to access our drive content. The first thing we need to do is grant programmatic access to our Google Drive account.
Head over to your Google Cloud Console and create a service account for your Google Drive access in your current project
Once the service account is created, generate a private key in json
and download the private key locally. We'll need this later.
Then enable access to the Google Drive API
At this point, we have a service account and have given the account access to the Google Drive API but we still haven't given the account access to OUR Google Drive. In our case, I created a Google Drive folder for the client and shared it with them. We also need to give the service account access to that same folder.
Now we're ready to head over to our Laravel project. We will be using the Google API SDK so install that via composer
1composer require google/apiclient
Next, we need to place our credentials.json
file into our storage/app
directory. This will allow the API to authenticate as our service account.
Let's create a class called GoogleDriveController.php
in our app\Classes
directory. Let's create a getFilesFromGoogleDrive
function where we can test this out. First, we'll make a connection to the Google Drive Client.
1 2public function getFilesFromGoogleDrive() 3{ 4 if (!file_exists(config('services.google_drive.credentials_file'))) { 5 throw new \Exception('Cannot find credentials file'); 6 } 7 8 $scopes = []; 9 10 $client = new \Google_Client();11 $client->setScopes($scopes);12 $client->setAuthConfig(config('services.google_drive.credentials_file'));13 $client->setAccessType('offline');14 $client->setRedirectUri(Request::url());15 16}
The Google Drive Client API needs to know how to authenticate us and also what scopes we are requesting access to. You can find more about Google Drive scopes here.
Now that we have our client established, let's make some calls to the Google Drive API. We'll add to the getFilesFromGoogleDrive
method above
1// Access the Google Drive Service 2$service = new \Google_Service_Drive($client); 3 4// List of options for retreiving files 5$optParams = [ 6 'pageSize' => 100, 7 'fields' => 'nextPageToken, files(id, name)', 8]; 9 10 $files = [];11$pageToken = null;12 13do {14 try {15 if ($pageToken !== null) {16 $optParams['pageToken'] = $pageToken;17 }18 19 $response = $service->files->listFiles($optParams);20 21 $files = array_merge($files, $response->files);22 23 $pageToken = $response->getNextPageToken();24 } catch (Exception $exception) {25 $pageToken = null;26 }27} while ($pageToken !== null);
Here's what we just did. First, we set up our Google Drive Service by instantiating it and passing our auth client. Once we have that established we use the listFiles
method and give it the parameters we want to retrieve. we are wrapping this in a do while
loop so we are sure to get all files in case there are multiple pages. Each iteration of the loop passes the nextPageToken
keeping track of where we are. When the files are returned we merge them with the existing $files
variable. After it's done retrieving the files we will have an array containing all the file ids and names.
Let's say we wanted to get an individual file and its contents. We can do that by calling the get()
method on the Google Drive service
1$fileId = 'Xw4r04304s2324234l'; // File ID2$content = '';3 4$file = $service->files->get($fileId, ['alt' => 'media']);5 6while (!$file->getBody()->eof()) {7 $content .= $file->getBody()->read(1024);8}
The get()
will return the file metadata but if you want to download the file, supply the ['alt' => 'media']
option when calling the method to get the actual contents.
Now that we have the ability to crawl our Google Drive folder and retrieve the files, we can create a Laravel scheduled task to retrieve those files on a given interval
In this blog, you learned how to create a Google Drive service account and link it to a shared folder in your Google Drive. You were then able to use the Google API SDK in your project to list the contents of your Google Drive and download files from it. You can further expand on this by adding your own methods to add or delete files and folders.