Skip to content

Instantly share code, notes, and snippets.

@hiroshil
Last active November 27, 2024 02:45
Show Gist options
  • Save hiroshil/927155dac02253e50fb3430f87f9214d to your computer and use it in GitHub Desktop.
Save hiroshil/927155dac02253e50fb3430f87f9214d to your computer and use it in GitHub Desktop.
Script to upload files or folders to a Google Drive folder using PyDrive2 (with Tqdm progress bar supported)
import re
from pathlib import Path
from tqdm import tqdm as Tqdm
from pydrive2.auth import GoogleAuth
from pydrive2.drive import GoogleDrive
param = "FolderID" #FileID is the simple file hash, like 0B1NzlxZ5RpdKS0NOS0x0Ym9kR0U
err_fmt = False
if len(param) > 33:
match = re.search(r"https:\/\/drive\.google\.com\/drive\/folders\/([^/]+)\/view\?usp=drive_link", param)
if match:
PARENT_ID = match.group(1)
else:
err_fmt = True
elif len(param) < 33:
err_fmt = True
else:
PARENT_ID = param
if err_fmt:
print("String not found in the any format.")
exit()
LOCAL_PATH = 'FOLDER_OR_FILE_PATH'
gauth = GoogleAuth()
# use any auth method that you like, in my case i use this one
# Try to load saved client credentials
gauth.LoadCredentialsFile("credentials.json")
if gauth.credentials is None:
# Authenticate if they're not there
# This is what solved the issues: https://stackoverflow.com/questions/24419188/automating-pydrive-verification-process/55876179#55876179
gauth.GetFlow()
gauth.flow.params.update({'access_type': 'offline'})
gauth.flow.params.update({'approval_prompt': 'force'})
gauth.LocalWebserverAuth()
elif gauth.access_token_expired:
# Refresh them if expired
gauth.Refresh()
else:
# Initialize the saved creds
gauth.Authorize()
# Save the current credentials to a file
gauth.SaveCredentialsFile("credentials.json")
drive = GoogleDrive(gauth)
def upload_single_file(item, parent_id):
# Upload a file to Google Drive
myFileName = item.name
# Check if file name already exists in folder.
file_list = drive.ListFile(
{
"q": '"{}" in parents and title="{}" and trashed=false'.format(
parent_id, myFileName
)
}
).GetList()
# If file is found, update it, otherwise create new file.
if len(file_list) == 1:
myFile = file_list[0]
else:
myFile = drive.CreateFile(
{"parents": [{"kind": "drive#fileLink", "id": parent_id}]}
)
# The `convert` flag indicates to Google Drive whether to convert the
# uploaded file into a Google Drive native format, i.e. Google Sheet for
# CSV or Google Document for DOCX.
# myFile.Upload({"convert": True})
no_progress_bar=False
progress_name=""
with open(item, "rb") as fobj:
total = item.stat().st_size
with Tqdm.wrapattr(
fobj,
"read",
desc=progress_name,
total=total,
disable=no_progress_bar,
) as wrapped:
# PyDrive doesn't like content property setting for empty files
# https://github.com/gsuitedevs/PyDrive/issues/121
if total:
myFile.content = wrapped
myFile["title"] = myFileName
myFile.Upload({"convert": True})
print(f"Uploaded file: {str(item)}")
def upload_folder(folder_path, parent_id, drive):
for item in folder_path.iterdir():
if item.is_dir():
# Create a new folder in Google Drive
folder = drive.CreateFile({'title': item.name, 'parents': [{'id': parent_id}], 'mimeType': 'application/vnd.google-apps.folder'})
folder.Upload()
print(f"Created folder: {item.name}")
# Recursively upload contents of the subfolder
upload_folder(item, folder['id'], drive)
else:
upload_single_file(item, parent_id)
input_path = Path(LOCAL_PATH)
if input_path.is_dir():
upload_folder(input_path, PARENT_ID, drive)
else:
upload_single_file(input_path, PARENT_ID)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment