The Google Drive API for the very, very beginner.

fredysandoval

Fredy Sandoval

Posted on July 12, 2022

The Google Drive API for the very, very beginner.

An easy to understand guide on how to use the Google Drive API


Table of contents

What its used for

In simple words: it help us to send HTTP requests in a way that the Google servers can accept, allowing us to manipulate the the Google Drive files.

Types of Authentication

The first step is to decide the authentication method, here are the option and use cases:

  • API key

    Use this credential to access/get publicly-available data anonymously, this means files set as "anyone with the link", you can't set/insert data just read it. you can safely expose this key to the user, since you can control the request via Google Cloud Platform.

  • OAuth client ID

    Use this credential to authenticate as an end user and access their data. Requires your app to request and receive consent from the user via OAuth, this requires a server in the middle to handle the keys, since this can't be expose to the end user.

  • Service account

    Use this credential to authenticate as a service account or to access files on behalf of Google Workspace. This service accounts can't be accessed using a username or password, you must be careful with the keys since it can compromise your Google Account.

How to Get the keys:

Authenticating our Application

Using API key

const { google } = require('googleapis');

const API_KEY = 'RanD0mK3Y-abcdevwefw-1234567890';

async function main() {
    const drive = google.drive({ version: 'v3', auth: API_KEY });
    console.log(drive);
}
Enter fullscreen mode Exit fullscreen mode

Using Google OAuth client ID

const { google } = require('googleapis');
const fs = require('fs');
const readline = require('readline');
const SCOPES = ['https://www.googleapis.com/auth/drive']; // Allows all scopes 
const TOKEN_PATH = './token.json'; // If this file doesn't exist, will be created later.
const CREDENTIALS_PATH = './client_secret_1234567890.json' // replace name with your secret file
let credentials, token;
// Getting credentials
try {
    const file = await fs.promises.readFile(CREDENTIALS_PATH);
    credentials = JSON.parse(file);
} catch (err) {
    console.error('Unable to read file:', err);
}
const { installed: { client_id, client_secret, redirect_uris } } = credential;
const oAuth2Client = new google.auth.OAuth2(client_id, client_secret, redirect_uris[0]);
// Getting Token
try {
    const file = await fs.promises.readFile(TOKEN_PATH);
    token = JSON.parse(file);
} catch (err) {
    const authUrl = oAuth2Client.generateAuthUrl({
        access_type: 'offline',
        scope: SCOPES,
    });
    console.log('Authorize this app by visiting this url:', authUrl);
    const rl = readline.createInterface({
        input: process.stdin,
        output: process.stdout,
    });
    rl.question('Enter the code from that page here: ', (code) => {
        rl.close();
        oAuth2Client.getToken(code, async (err, r_token) => {
            if (err) reject(err);
            await fs.promises.writeFile(TOKEN_PATH, JSON.stringify(r_token), (err) => {
                if (err) reject(err);
                console.log('Token stored to', `./${TOKEN_PATH}`);
            });
            token = r_token;
        });
    });
}
// Setting token 
oAuth2Client.setCredentials(token);
const drive = google.drive({ version: 'v3', auth: oAuth2Client });
Enter fullscreen mode Exit fullscreen mode

Using Service account

const { google } = require('googleapis');
const path = require('path');

const KEYFILEPATH = path.join(__dirname, 'service.json');
const SCOPES = ['https://www.googleapis.com/auth/drive'];

const auth = new google.auth.GoogleAuth({
    keyFile: KEYFILEPATH,
    scopes: SCOPES,
});
const drive = google.drive({ version: 'v3', auth });
Enter fullscreen mode Exit fullscreen mode

Sending a request

Regardless of the method or programming language we use, the HTTP request that Google will receive, looks like this:

  • Using the API key
GET /drive/v3/files/AbCdEFGhijklmopr-abcde_fghijl-oqQrstuvWxyZ?fields=kind%2C%20id%2C%20name&key=Abcdefghij-KmnloprstuVwxyZ HTTP/1.1
Host: googleapis.com
User-Agent: google-api-nodejs-client/0.7.2 (gzip)
Accept: application/json
Accept-Encoding: gzip
X-Forwarded-For: 190.191.192.193
X-Forwarded-Proto: https
Enter fullscreen mode Exit fullscreen mode
  • Using the OAuth client ID
GET /drive/v3/files/17qEQsVNm-XWtdGSWy2_p0-pyoLaZS0mq16L1mKX2it4?fields=kind%2C%20id%2C%20name HTTP/1.1
Host: googleapis.com 
User-Agent: google-api-nodejs-client/0.7.2 (gzip)
Accept: application/json
Accept-Encoding: gzip
Authorization: Bearer ya12.RaNdOmStRinG1234RaNdOmStRinG1234RaNdOmStRinG1234-RaNdOmStRinG1234_RaNdOmStRinG1234_RaNdOmStRinG1234
X-Forwarded-For: 190.191.192.193
X-Forwarded-Proto: https
Enter fullscreen mode Exit fullscreen mode

Sending the same request with the Google APIs Node.js Client package will look like this:

// The authentication was done using the previous methods
const path_parameters = {
    fileId: 'AbCdEFGhijklmopr-abcde_fghijl-oqQrstuvWxyZ',
    fields: 'kind, id, name',
}
const result = await drive.files.get(path_parameters, options);
Enter fullscreen mode Exit fullscreen mode

File Methods, examples:

set root Url

You can send the HTTP request to a different server, for example you can send the request to a ngrok https server tunneling ncat to output all the incoming requests, this can be useful if you want to see what exactly is receiving the server.

const options = {
    rootUrl: 'https://www.googleapis.com',
}
// const options = {
//     rootUrl: 'https://1234-199-199-199-199.ngrok.io/'
// }
Enter fullscreen mode Exit fullscreen mode

copy

const parents = ['YOUR_PARENT_ID_IN_ARRAY'];
const fileId = 'YOUR_ID_OF_THE_FILE_TO_BE_COPIED';
const name = 'YOUR_NEW_NAME';
const path_parameters = {
    fileId: fileId,
    fields: 'kind, id, name',
    resource: {
        name: name,
        parents: parents,
    },
}
const result = await drive.files.copy(path_parameters, options);
Enter fullscreen mode Exit fullscreen mode

create

  • create a new folder
const parents = ['YOUR_PARENT_FOLDER_OPTIONAL'];
const name = 'YOUR_NEW_FOLDER_NAME';
const path_parameters = {
    resource: {
        name: name, 
        mimeType: 'application/vnd.google-apps.folder',
        parents: parents,
    },
    fields: 'kind, id, name',
}
const result = await drive.files.create(path_parameters, options);
Enter fullscreen mode Exit fullscreen mode
  • Upload a new file
const path_parameters = {
    resource: {
        name: 'YOUR_NEW_FILE_NAME',
        parents: ['YOUR_PARENTS_IDs_OPTIONAL'],
    },
    media: {
        body: 'YOUR_READABLE_STREAM',
    },
    fields: 'kind, id, name',
}

const result = await drive.files.create(path_parameters, options);
Enter fullscreen mode Exit fullscreen mode

delete

const path_parameters = {
    fileId: 'YOUR_FILE_ID',
    fields: 'kind, id, name',
}
const result = await drive.files.delete(path_parameters, options);
Enter fullscreen mode Exit fullscreen mode

empty trash

await drive.files.emptyTrash({});
Enter fullscreen mode Exit fullscreen mode

export

For a list of avaiable mimeTypes available visit this link

const path_parameters = {
    fileId: 'YOUR_FILE_ID',
    mimeType: 'THE MIMETYPE',
    fields: 'kind, id, name',
}
const options = {
    responseType: 'stream',
    rootUrl: 'https://www.googleapis.com',
}
const result = await drive.files.export(path_parameters, options);
Enter fullscreen mode Exit fullscreen mode

generateIds

const fields = 'kind, space, ids';
const path_parameters = {
    count: 3, // the number of IDs you want
    fields: fields,
}
const result = await drive.files.generateIds(path_parameters, options);
Enter fullscreen mode Exit fullscreen mode

get

const path_parameters = {
    fileId: 'YOUR_FILE_ID',
    fields: 'kind, id, name',
}
const result = await drive.files.get(path_parameters, options);
Enter fullscreen mode Exit fullscreen mode

list

For a list of query string parameters visit this link

const fields = "kind, nextPageToken ,files(kind, id, name)";
const query = "YOUR_QUERIES";
const nextPageToken = "TO_CONTINUE_WITH_A_PREVIOUS_LIST";
const path_parameters = {
    q: query,
    pageSize: 5, // Number of files returned
    fields: fields,
    pageToken: nextPageToken, // optional
}
const listFiles = await drive.files.list(path_parameters, options);
Enter fullscreen mode Exit fullscreen mode

update

const path_parameters = {
    fileId: "YOUR_FILE_ID",
    fields: 'kind, id, name',
    resource: {
        trashed: true, // This will send the file to trash
        name: 'YOUR_NEW_FILE_NAME'
    },
}
const result = await drive.files.update(path_parameters, options);
Enter fullscreen mode Exit fullscreen mode

watch

This will send a HTTP request to the address every time the file is modified

// use https://github.com/uuidjs/uuid to generate a unique id
const channelId = "01234567-89ab-cdef-0123456789ab";
const path_parameters = {
    fileId: 'THE_ID_OF_THE_FILE_YOU_WANT_TO_WATCH',
    supportsAllDrives: true,
    supportsTeamDrives: true,
    requestBody: {
        id: channelId,
        type: "web_hook",
        address: "https://example.com/webhook",
        payload: true,
    },
}
const result = await drive.files.watch(path_parameters, options);
Enter fullscreen mode Exit fullscreen mode

stop

This will stop or unwatches the provious watch file

const channelId = "01234567-89ab-cdef-0123456789ab";
const path_parameters = {
    requestBody: {
        id: channelId,
        // The watch function returns this value
        resourceId: 'abcdeF-GHIJKLMNOPQRSTUVW',
    },
}
const result = await drive.channels.stop(path_parameters, options);
Enter fullscreen mode Exit fullscreen mode

Check my repo for the code github.com/FredySandoval/google-drive-api-usage-examples

💖 💪 🙅 🚩
fredysandoval
Fredy Sandoval

Posted on July 12, 2022

Join Our Newsletter. No Spam, Only the good stuff.

Sign up to receive the latest update from our blog.

Related