PHP Google Drive API | List, Create Folders, Sub Folders and Upload Files

In this tutorial, you’ll learn Google Drive API and also List, Create and Upload Files to the drive.

Table Of Contents

Enable Google Driver API

Enabling the API is the first step in creating a simple file upload application. Log in to Google and visit

Google Drive - Enable API Key
Google Drive – Enable API Key

Creating a Project in Google Driver API

After clicking on Enable the Driver button you’ll see a modal that asks you to give the project a name.

Google Drive - Give Name to Project
Give Name to Project

Then the next step is to select the mode through which you will be using this API. Here you select Web Browser as an option.

Google Drive - Select the Mode
Select the Mode

Configure OAuth Client

After the selection of mode, you will be prompted with the Origin URL. You will access the drive information through this URL. So, our current URL will be http://localhost.

Configure your Oauth Client
Configure your Oauth Client

Client Configuration File

In the Final Step, you will see a download button that tells you to Download Client Configuration. This file is of type JSON format and contains client ID, client secret, redirect_uris, and javascript_origins.
So download it and save it in your project root without changing its name.

Final step is to download client configuration
Final step is to download client configuration

Installation and Configure Google Client Library in your project

Open terminal in your project root and type below command. This will install the apiclient into your project.

composer require google/apiclient:^2.0
PS C:\xampp\htdocs\examples> composer require google/apiclient:^2.0
./composer.json has been created
Loading composer repositories with package information
Updating dependencies (including require-dev)
Package operations: 12 installs, 0 updates, 0 removals
    - Installing psr/http-message (1.0.1): Loading from cache
    - Installing guzzlehttp/psr7 (1.2.3): Downloading (100%)
    - Installing guzzlehttp/promises (v1.3.1): Loading from cache
    - Installing guzzlehttp/guzzle (6.2.0): Downloading (100%)
    - Installing phpseclib/phpseclib (2.0.28): Downloading (100%)
    - Installing psr/log (1.1.3): Downloading (100%)
    - Installing monolog/monolog (1.25.4): Downloading (100%)
    - Installing firebase/php-jwt (v3.0.0): Downloading (100%)
    - Installing google/apiclient-services (v0.139): Downloading (100%)
    - Installing psr/cache (1.0.1): Downloading (100%)
    - Installing google/auth (v0.8): Downloading (100%)
    - Installing google/apiclient (v2.0.0): Downloading (100%)
phpseclib/phpseclib suggests installing ext-libsodium (SSH2/SFTP can make use of some algorithms provided by the libsodium-php extension.)
phpseclib/phpseclib suggests installing ext-mcrypt (Install the Mcrypt extension in order to speed up a few other cryptographic operations.)
phpseclib/phpseclib suggests installing ext-gmp (Install the GMP (GNU Multiple Precision) extension in order to speed up arbitrary precision integer arithmetic operations.)
monolog/monolog suggests installing graylog2/gelf-php (Allow sending log messages to a GrayLog2 server)
monolog/monolog suggests installing sentry/sentry (Allow sending log messages to a Sentry server)
monolog/monolog suggests installing doctrine/couchdb (Allow sending log messages to a CouchDB server)
monolog/monolog suggests installing ruflin/elastica (Allow sending log messages to an Elastic Search server)
monolog/monolog suggests installing php-amqplib/php-amqplib (Allow sending log messages to an AMQP server using php-amqplib)
monolog/monolog suggests installing ext-amqp (Allow sending log messages to an AMQP server (1.0+ required))
monolog/monolog suggests installing ext-mongo (Allow sending log messages to a MongoDB server)
monolog/monolog suggests installing mongodb/mongodb (Allow sending log messages to a MongoDB server via PHP Driver)
monolog/monolog suggests installing aws/aws-sdk-php (Allow sending log messages to AWS services like DynamoDB)
monolog/monolog suggests installing rollbar/rollbar (Allow sending log messages to Rollbar)
monolog/monolog suggests installing php-console/php-console (Allow sending log messages to Google Chrome)
google/apiclient suggests installing tedivm/stash (For caching certs and tokens (using Google_Client::setCache))
Writing lock file
Generating autoload files
2 packages you are using are looking for funding.
Use the `composer fund` command to find out more!

Creating Google_Client class

The class Google_Client is used for authorization of a client and set scopes such as read-only, file access, etc.
If you want to upload files then your scope must be set to Google_Service_Drive::DRIVE which internally points to URL https://www.googleapis.com/auth/drive.

Info

Click here to know more about scopes.

Here is how the class looks google-drive.php.

<?php
require __DIR__ . '/vendor/autoload.php';


/**
    * Returns an authorized API client.
    * @return Google_Client the authorized client object
    */ 
function getClient()
{
    $client = new Google_Client();

    $client->setApplicationName('Google Drive API PHP Quickstart');
    $client->setRedirectUri('http://localhost/test-examples/php/google-drive-api/oauth2callback.php');

    $client->setScopes(Google_Service_Drive::DRIVE);
    $client->setAuthConfig('credentials.json');
    $client->setAccessType('offline');
    $client->setPrompt('select_account consent');

    // Load previously authorized token from a file, if it exists.
    // The file token.json stores the user's access and refresh tokens, and is
    // created automatically when the authorization flow completes for the first
    // time.
    $tokenPath = 'token.json';
    if (file_exists($tokenPath)) {
        $accessToken = json_decode(file_get_contents($tokenPath), true);
        $client->setAccessToken($accessToken);
    }

    // If there is no previous token or it's expired.
    if ($client->isAccessTokenExpired()) {
        // Refresh the token if possible, else fetch a new one.
        if ($client->getRefreshToken()) {
            $client->fetchAccessTokenWithRefreshToken($client->getRefreshToken());
        } else {
            // Request authorization from the user.
            $authUrl = $client->createAuthUrl();
            printf("Open the following link in your browser:\n%s\n", $authUrl);
            print 'Enter verification code: ';
            $authCode = trim(fgets(STDIN));

            // Exchange authorization code for an access token.
            $accessToken = $client->fetchAccessTokenWithAuthCode($authCode);
            $client->setAccessToken($accessToken);

            // Check to see if there was an error.
            if (array_key_exists('error', $accessToken)) {
                throw new Exception(join(', ', $accessToken));
            }
        }
        // Save the token to a file.
        if (!file_exists(dirname($tokenPath))) {
            mkdir(dirname($tokenPath), 0700, true);
        }
        file_put_contents($tokenPath, json_encode($client->getAccessToken()));
    }
    return $client;
}

// Get the API client and construct the service object.
$client = getClient();

In order to access the files from the cloud, you have to create a verification code.

Generating Access Token

Go to the root project and open terminal and type below command.

php google-drive.php

This will display a URL when clicked open in your browser and asks you to log in and authorize this request. After client authentication, you will be prompted with verification code and you have to paste it here.

Udemy PHP Course
Udemy PHP Course

Project File Structure

Your-Project
    |-- uploads
    |-- vendor
    |-- composer.json
    |-- composer.lock
    |-- credentials.json //contains google client credentials
    |-- form.php // HTML form to upload files
    |-- google-drive.php // contains instance of API client
    |-- oauth2callback.php // Just a php page that used for redirect uri and also contains verification code
    |-- submit.php // here go our main business logic of listing, creating and uploading files.
    |-- token.json // OAuth token this is generated automatically once you enter verification code.

Upload File to Drive using HTML form

Let’s try to upload a file into google drive using the form method.

form.php

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>File Upload</title>
</head>
<body>
    <h2>PHP Google Drive Api </h2>
    <a href="submit.php?list_files_and_folders=1">Click here to list all files and folders</a>

    <h2>File Upload</h2>
    <form action="submit.php" method="post" enctype="multipart/form-data" >
        <label for="">Choose File</label>
        <input type="file" name="file" >
        
        <input type="submit" name="submit" value="submit" >
    </form>
</body>
</html>

submit.php

Backend code for file upload.

<?php
error_reporting(E_ERROR | E_PARSE);
require __DIR__ . '/google-drive.php';

if( isset( $_POST['submit'] ) ){
    
    if( empty( $_FILES["file"]['tmp_name'] ) ){
        echo "Go back and Select file to upload.";
        exit;
    }
    
    $file_tmp  = $_FILES["file"]["tmp_name"];
    $file_type = $_FILES["file"]["type"];
    $file_name = basename($_FILES["file"]["name"]);
    $path = "uploads/".$file_name;

    move_uploaded_file($file_tmp, $path);

    $folder_id = create_folder( "google-drive-test-folder" );

    $success = insert_file_to_drive( $path , $file_name, $folder_id);

    if( $success ){
        echo "file uploaded successfully";
    } else { 
        echo "Something went wrong.";
    }
}

// This will create a folder and also sub folder when $parent_folder_id is given
function create_folder( $folder_name, $parent_folder_id=null ){

    $folder_list = check_folder_exists( $folder_name );

    // if folder does not exists
    if( count( $folder_list ) == 0 ){
        $service = new Google_Service_Drive( $GLOBALS['client'] );
        $folder = new Google_Service_Drive_DriveFile();
    
        $folder->setName( $folder_name );
        $folder->setMimeType('application/vnd.google-apps.folder');
        if( !empty( $parent_folder_id ) ){
            $folder->setParents( [ $parent_folder_id ] );        
        }

        $result = $service->files->create( $folder );
    
        $folder_id = null;
        
        if( isset( $result['id'] ) && !empty( $result['id'] ) ){
            $folder_id = $result['id'];
        }
    
        return $folder_id;
    }

    return $folder_list[0]['id'];
    
}

// This will check folders and sub folders by name
function check_folder_exists( $folder_name ){
    
    $service = new Google_Service_Drive($GLOBALS['client']);

    $parameters['q'] = "mimeType='application/vnd.google-apps.folder' and name='$folder_name' and trashed=false";
    $files = $service->files->listFiles($parameters);

    $op = [];
    foreach( $files as $k => $file ){
        $op[] = $file;
    }

    return $op;
}

// This will display list of folders and direct child folders and files.
function get_files_and_folders(){
    $service = new Google_Service_Drive($GLOBALS['client']);

    $parameters['q'] = "mimeType='application/vnd.google-apps.folder' and 'root' in parents and trashed=false";
    $files = $service->files->listFiles($parameters);
    
    echo "<ul>";
    foreach( $files as $k => $file ){
        echo "<li> 
        
            {$file['name']} - {$file['id']} ---- ".$file['mimeType'];

            try {
                // subfiles
                $sub_files = $service->files->listFiles(array('q' => "'{$file['id']}' in parents"));
                echo "<ul>";
                foreach( $sub_files as $kk => $sub_file ) {
                    echo "<li&gt {$sub_file['name']} - {$sub_file['id']}  ---- ". $sub_file['mimeType'] ." </li>";
                }
                echo "</ul>";
            } catch (\Throwable $th) {
                // dd($th);
            }
        
        echo "</li>";
    }
    echo "</ul>";
}

// This will insert file into drive and returns boolean values.
function insert_file_to_drive( $file_path, $file_name, $parent_file_id = null ){
    $service = new Google_Service_Drive( $GLOBALS['client'] );
    $file = new Google_Service_Drive_DriveFile();

    $file->setName( $file_name );

    if( !empty( $parent_file_id ) ){
        $file->setParents( [ $parent_file_id ] );        
    }

    $result = $service->files->create(
        $file,
        array(
            'data' => file_get_contents($file_path),
            'mimeType' => 'application/octet-stream',
        )
    );

    $is_success = false;
    
    if( isset( $result['name'] ) && !empty( $result['name'] ) ){
        $is_success = true;
    }

    return $is_success;
}

if( isset( $_GET['list_files_and_folders'] ) ){
    echo "<h1>Retriving List all files and folders from Google Drive</h1>";
    get_files_and_folders();
}

// Function just for easier debugging
function dd( ...$d ){
    echo "<pre style='background-color:#000;color:#fff;' >";
    print_r($d);
    exit;
}    

Functions and their purpose.

  • getClient(): This function returns authorized client object.
  • create_folder(): Creates folder or subfolder
  • check_folder_exists(): Before creating checks wheather folder exists using query terms.
  • insert_file_to_drive(): Inserts file into drive and returns boolean value true on success and false on failure.
  • get_files_and_folders(): Retrives root folder with files with their direct childrens.
  • dd(): This function is used to make debugging easier.

Output

Useful Links

Conclusion

In conclusion, we have come to end on our post on PHP Google Drive API | List, Create, and Upload Files. For any suggestions comment below.

Summary
Review Date
Reviewed Item
PHP Google Drive API | List, Create Folders, Sub Folders and Upload Files
Author Rating
51star1star1star1star1star
Software Name
Google Drive API
Software Name
Windows Os, Mac Os and Ubuntu Os
Software Category
PHP API Development