Google Drive API with Python – Upload & Download a file

For how to authenticate yourself please go watch this video.

You will need a token.json with this content in the root of your project:

{
  "token": "generated_access_token",
  "refresh_token": "generated_refresh_token",
  "token_uri": "https://oauth2.googleapis.com/token",
  "client_id": "your_client_id",
  "client_secret": "your_client_secret",
  "scopes": [
    "https://www.googleapis.com/auth/drive"
  ]
}

I will be using Google’s Quickstart as a foundation for what I am doing.

Upload

Let’s upload a file first. You will need an ID of a directory you will be uploading. The easiest way is to look at the browser link of your desired folder:

https://drive.google.com/drive/u/0/folders/<folder_id>

Now, let’s upload a file meme.jpg to the folder_id:

from __future__ import print_function
import os.path
from google.auth.transport.requests import Request
from google.oauth2.credentials import Credentials
from google_auth_oauthlib.flow import InstalledAppFlow
from googleapiclient.discovery import build
from googleapiclient.errors import HttpError
from apiclient.http import MediaFileUpload
from pathlib import Path


SCOPES = ['https://www.googleapis.com/auth/drive']


def main():
    creds = None
    if os.path.exists('token.json'):
        creds = Credentials.from_authorized_user_file('token.json', SCOPES)
    if not creds or not creds.valid:
        if creds and creds.expired and creds.refresh_token:
            creds.refresh(Request())
        else:
            flow = InstalledAppFlow.from_client_secrets_file(
                'credentials.json', SCOPES)
            creds = flow.run_local_server(port=0)
        with open('token.json', 'w') as token:
            token.write(creds.to_json())

    try:
        service = build('drive', 'v3', credentials=creds)
        file_metadata = {

            'name': 'meme.jpg',
            'parents': ['folder_id']

        }
        media = MediaFileUpload('meme.jpg', mimetype='image/jpg')
        file = service.files().create(body=file_metadata,
                                            media_body=media,
                                            fields='id').execute()

    except HttpError as error:
        # TODO(developer) - Handle errors from drive API.
        print(f'An error occurred: {error}')


if __name__ == '__main__':
    main()

My code worked for me:

Download

Now let’s download this image back to some directory on my computer. For that you will need the file id. The test way is to right click on the file and click “Get link”, but if you need to list directory content to get a bunch of files and their id, I will point you to the right direction:

results = drive_service.files().list(q="'" + folder_id + "' in parents", pageSize=200,fields="nextPageToken, files(id, name)").execute()

items = results.get('files', [])

Back to downloading:

from __future__ import print_function
import os.path
from google.auth.transport.requests import Request
from google.oauth2.credentials import Credentials
from google_auth_oauthlib.flow import InstalledAppFlow
from googleapiclient.discovery import build
from googleapiclient.errors import HttpError
# from apiclient.http import MediaFileUpload
from googleapiclient.http import MediaIoBaseDownload
from pathlib import Path
import io

SCOPES = ['https://www.googleapis.com/auth/drive']


def main():
    creds = None
    if os.path.exists('token.json'):
        creds = Credentials.from_authorized_user_file('token.json', SCOPES)
    if not creds or not creds.valid:
        if creds and creds.expired and creds.refresh_token:
            creds.refresh(Request())
        else:
            flow = InstalledAppFlow.from_client_secrets_file(
                'credentials.json', SCOPES)
            creds = flow.run_local_server(port=0)
        with open('token.json', 'w') as token:
            token.write(creds.to_json())

    try:
        service = build('drive', 'v3', credentials=creds)
        folder_path = 'test'

        Path(folder_path).mkdir(parents=True, exist_ok=True)

        filename = os.path.join(folder_path, 'meme.jpg')

        request = service.files().get_media(fileId='folder_id')
        fh = io.FileIO(filename, 'wb')
        downloader = MediaIoBaseDownload(fh, request)
        done = False
        while done is False:
            status, done = downloader.next_chunk()

    except HttpError as error:
        # TODO(developer) - Handle errors from drive API.
        print(f'An error occurred: {error}')


if __name__ == '__main__':
    main()

This code too worked for me:

Google APIs can be not very easy to crack, but looking for a solution is always rewarding.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

This site uses Akismet to reduce spam. Learn how your comment data is processed.