You are currently viewing <strong>How to use Google Drive as photo gallery via Google API</strong>

How to use Google Drive as photo gallery via Google API

The main goal of the Google Drive is acting as storage for the user files with the ability to share them. However, it is possible to use it as a photo gallery when a user uploads images to it and other applications display these images almost on any device with a browser that supports JavaScript.

It is also possible to use Google Photos with animation functionality; however, it requires rebuilding after a new image has been uploaded. Google Pages with Image carousel plugin or Google Slides require also to be updated after uploading a new image. Another possibility is to use 3rd party applications, e.g. Android apps on TV; however, it is not a general solution and some older TVs have no such functionality. Google App Script is the best alternative, but still it requires front-end diminishing its benefits.

Using Google Drive as images gallery can be done via Google API considering that the gallery will require at least the following functionality:

  • Authentication to Google Drive
  • Getting the list of folders
  • Getting the last update timestamp of the folder. 
  • Getting a list of images in particular Google Drive folder
  • Getting particular image

The examples are based on Node.js; however, it is possible to use other languages including java.

Authentication to Google Drive includes the following prerequisite steps:

  1. Creation of the Google service account

Google service accounts can be created using Google Cloud console -> IAM & Admin -> Service Accounts. If the application eventually will be deployed as Google App Engine, its service account can be used instead.

  1. Providing access to the Google API’s

The service account has to have access to the following Google API’s (go to Google Cloud console -> APIs & Services):

  • Google Drive API
  • Drive Activity API
  1. Providing access to Google Drive

Set READ permission for the Google service account to the Google Drive folder.

The images can be downloaded directly from the Google drive via the link:

https://drive.google.com/uc?id=xyz, where xyz shall be replaced with image id; however, for this case, allow “Viewer” access for “Anyone with the link” additional permissions shall be set in the Google Drive folder.

After these steps, JSON Web Token (JWT) is created that handles the authentication using Google library:
import { google } from 'googleapis';
function getAuth(){
const scopes = process.env.APP_SCOPE ? process.env.APP_SCOPE.split(',') : undefined;
const auth = new google.auth.JWT(
process.env.GOOGLE_CLIENT_EMAIL,
'',
process.env.GOOGLE_PRIVATE_KEY?.replace(/\\n/g, '\n'),
scopes
);
return auth;
}

It is always wise to store authorization related information in .env file (Google parameters are generated automatically via Google Cloud -> Service Accounts -> [Your service account] -> KEYS tab – > ADD KEY):
GOOGLE_TYPE=service_account GOOGLE_PROJECT_ID=<ADD_PROJECT_ID>
GOOGLE_PRIVATE_KEY_ID=<ADD_PRIVATE_KEY_ID> GOOGLE_PRIVATE_KEY=<ADD_PRIVATE_KEY>
GOOGLE_CLIENT_EMAIL=<ADD_GOOGLE_SERVICE_ACCOUNT_EMAIL>
GOOGLE_CLIENT_ID=<ADD_GOOGLE_SERVICE_ACCOUNT_ID>
GOOGLE_AUTH_URI=https://accounts.google.com/o/oauth2/auth
GOOGLE_TOKEN_URI=https://oauth2.googleapis.com/token
GOOGLE_AUTH_PROVIDER_X509_CERT_URL=https://www.googleapis.com/oauth2/v1/certs
GOOGLE_CLIENT_X509_CERT_URL=https://www.googleapis.com/robot/v1/metadata/x509/<ADD_SERVICE_ACCOUNT_NAME>%40<ADD_PROJECT_ID>.iam.gserviceaccount.com
APP_SCOPE=https://www.googleapis.com/auth/drive,https://www.googleapis.com/auth/drive.activity.readonly

Getting the list of folders” feature is needed to know from what folders, including shared folders, the images can be taken.
export async function getFolders(){
const auth = getAuth();
const drive = google.drive({ version: 'v3', auth });
var folders: { name: string | null | undefined; }[];
try{
const params = {
q: `(mimeType = 'application/vnd.google-apps.folder') and trashed = false`,
fields: 'files(id,name)',
orderBy: 'createdTime desc',
includeItemsFromAllDrives: true,
supportsAllDrives: true,
}; const res = await drive.files.list(params);
const files = res.data.files || [];
folders = files.map( ({id,name}) => ({id,name}) );
}catch(e: unknown){
const err = e as Error;
return Error(`Error while getting folders:` + err.message);
}
return folders;
}

Getting the last update timestamp of the folder” feature is needed to query a list of images only when the folder has been updated.
export async function getLastModifiedTime(folderId: string) {
const auth = getAuth();
var res = null;
try{
const service = google.driveactivity({ version: 'v2', auth });
const params = {
ancestorName: 'items/' + folderId,
};
res = await service.activity.query({ requestBody: params });
}catch(e: unknown){
const err = e as Error;
return Error(`Error while getting last modified time of the folder (${folderId}): ` + err.message);
}
const activities = res.data.activities;
if (!activities || activities.length === 0) {
return;
}
return activities[0].timestamp;
}

Getting a list of images in particular Google Drive folder. Basically, the following function returns the array of id’s of the images ordered by createdTime desc.
export async function getImagesFromFolder(folderId: string){
const auth = getAuth();
const drive = google.drive({ version: 'v3', auth });
var fileIds: (string | null | undefined)[] = [];
try{
const params = {
q: `(mimeType = 'image/jpeg' or mimeType = 'image/png') and trashed = false and parents in '${folderId}'`,
fields: 'files(id)',
orderBy: 'createdTime desc',
includeItemsFromAllDrives: true,
supportsAllDrives: true,
}; const res = await drive.files.list(params);
const files = res.data.files || [];
fileIds = files.map((file) => file.id);
}catch(e: unknown){
const err = e as Error;
return Error(`Error while getting images from folder (${folderId}):` + err.message); }
return fileIds;
}

Getting particular image is implemented via the following function which returns Buffer variable:
export async function getImage(fileId: string) {
const auth = getAuth();
const drive = google.drive({ version: 'v3', auth });
const chunks: Uint8Array[] = [];
return drive.files
.get({fileId, alt: 'media'}, {responseType: 'stream'})
.then(res => {
return new Promise((resolve, reject) => {
res.data
.on('end', () => resolve(Buffer.concat(chunks)))
.on('error', err => {
console.error('Error downloading file.');
reject(err);
})
.on('data', (chunk) => chunks.push(Buffer.from(chunk)))
});
});
}

After the back-end is completed, it is possible to build the front-end with an image carousel React component, e.g. https://www.npmjs.com/package/react-responsive-carousel.

Of course, there are plenty of ways for improving this code and adding functionalities (e.g. saving updated image back to the Google Drive folder); nonetheless, this article might be a simple basis for it saving developer’s time for surfing the internet for related information.

References

  1. Authentication to Google Drive
    1. How to Use the Google Drive API with JavaScript
  2. Getting list of images in particular Google Drive folder
    1. Search for files and folders
    2. Files: list
    3. Search query terms and operators
    4. Return specific fields for a file
    5. Method: drive.files.list
  3. Getting the last update timestamp of the folder.
    1. Method: activity.query
    2. Node.js quickstart
    3. How to check if content of google drive folder has changed?
  4. Getting particular image
    1. Express equivalent of res.end(data, ‘binary’)?
    2. How do I read the contents of a Node.js stream into a string variable?
    3. Send image generated with node-gd to client
    4. googleapis/google-api-nodejs-client
  5. Displaying images directly from Google Drive
    1. How do I display images from Google Drive on a website?
    2. How can I show images from a Google Drive folder?

Leave a Reply