Python Google Drive Api to Sync Folder

Aug 22, 2018

I have a local directory which I might add files or remove files. I want to upload added files to Google Drive and remove deleted files from Google Drive as well. These files should be stored within a folder in Google Drive.

To get CREDENTIAL_FILE (.json), goto Google API Console -> Library and enable Google Drive API. Then goto Google API Console -> Credentials -> Create Credential -> OAuth client ID, I select Other as Application type (since I am writing a Python script, not a Web application). Click Download JSON icon to get the credential json file.

Install Google Client Library.

pip install --upgrade google-api-python-client oauth2client

The following script

  • Create a GDrive folder if not already exist
  • Query GDrive folder's ID
  • Query all files within the GDrive folder
  • Query local files in directory and upload files which doesn't exist in GDrive folder
  • Delete files in GDrive folder which no longer exist in local directory
from __future__ import print_functionimport osimport globfrom googleapiclient.discovery import buildfrom googleapiclient.http import MediaFileUploadfrom httplib2 import Httpfrom oauth2client import file as oauth2file, client, toolsSCOPES = 'https://www.googleapis.com/auth/drive'CREDENTIAL_FILE = 'gdrive_sync_credential.json'TOKEN_FILE = 'gdrive_sync_token.json'def sync_folder(local_folder, gdrive_folder_name):    store = oauth2file.Storage(TOKEN_FILE)    creds = store.get()    if not creds or creds.invalid:        flow = client.flow_from_clientsecrets(CREDENTIAL_FILE, SCOPES)        creds = tools.run_flow(flow, store)    service = build('drive', 'v3', http=creds.authorize(Http()))    drive_service = service    file_metadata = {        'name': gdrive_folder_name,        'mimeType': 'application/vnd.google-apps.folder'    }    response = drive_service.files().list(q="name='{name}' and mimeType='{mimeType}'".format(name=file_metadata['name'], mimeType=file_metadata['mimeType'])).execute()    items = response.get('files', [])    if not items:        print("'{0}'' not found, create new".format(file_metadata['name']))        file = drive_service.files().create(body=file_metadata,                                            fields='id').execute()    else:        print("'{0}'' found".format(file_metadata['name']))        file = items[0]    folder_id = file.get('id')    print("folderId={0}".format(folder_id))    # check files on gdrive    response = drive_service.files().list(q="'{folderId}' in parents".format(folderId=folder_id)).execute()    drive_filenames = {}    for _file in response.get('files', []):        drive_filenames[_file.get('name')] = _file.get('id')    print("drive_filenames={0}".format(len(drive_filenames)))    # only upload new files    for _file in glob.glob(local_folder + '/*.gz'):        filename = os.path.basename(_file)        if filename not in drive_filenames:            print("Upload {0}".format(filename))            file_metadata = {                'name': filename,                'parents': [folder_id],            }            media = MediaFileUpload(_file, mimetype='application/gzip')            file = drive_service.files().create(body=file_metadata,                                                media_body=media,                                                fields='id').execute()            print("Uploaded: {0}".format(file.get('id')))        else:            print("{0} Exist".format(filename))    # delete files no longer exist in local    for _file, _id in drive_filenames.iteritems():        print("Delete '{0}', {1}".format(_file, _id))        drive_service.files().delete(fileId=_id).execute()

NOTE: The script only check filename, and doesn't reupload file when content changed but filename doesn't change.

NOTE: Web authentication is only required the first time, after which the authorization should be stored in TOKEN_FILE. Web authentication is required again if SCOPES changed.

References:

❤️ Is this article helpful?

Buy me a coffee ☕ or support my work via PayPal to keep this space 🖖 and ad-free.

Do send some 💖 to @d_luaz or share this article.

✨ By Desmond Lua

A dream boy who enjoys making apps, travelling and making youtube videos. Follow me on @d_luaz

👶 Apps I built

Travelopy - discover travel places in Malaysia, Singapore, Taiwan, Japan.