Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Create a folder (if not exists) on google drive and upload a file to it using Python script

So far I can upload file to the folder if it exists. I can't figure out a way to create one though. So if the folder does not exist, my script dies.

import sys
from pydrive.auth import GoogleAuth
from pydrive.drive import GoogleDrive

gpath = '2015'
fname = 'Open Drive Replacements 06_01_2015.xls'

gauth = GoogleAuth()
gauth.LocalWebserverAuth()
drive = GoogleDrive(gauth)

file_list = drive.ListFile({'q': "'root' in parents and trashed=false"}).GetList()
for file1 in file_list:
    if file1['title'] == gpath:
        id = file1['id']

file1 = drive.CreateFile({'title': fname, "parents":  [{"kind": "drive#fileLink","id": id}]})
file1.SetContentFile(fname)
file1.Upload()

Can you please help me modify the above code to create folder gpath if it does not exist?

like image 261
Akshay Kalghatgi Avatar asked Jun 01 '15 23:06

Akshay Kalghatgi


People also ask

How do I automatically add folders to Google Drive?

Sync Files Using Google Drive Backup and Sync Simply install Backup and Sync and you can add any folder on your computer to automatically upload all files to Google Drive. You'll also get a new Google Drive folder on your computer.


2 Answers

Based on the documentation, it should be

file1 = drive.CreateFile({'title': fname, 
    "parents":  [{"id": id}], 
    "mimeType": "application/vnd.google-apps.folder"})

Update: As of Apr 2020, documentation (v3) has been updated with API docs and shows:

folder_id = '0BwwA4oUTeiV1TGRPeTVjaWRDY1E'
file_metadata = {
    'name': 'photo.jpg',
    'parents': [folder_id]
}
media = MediaFileUpload('files/photo.jpg',
                        mimetype='image/jpeg',
                        resumable=True)
file = drive_service.files().create(body=file_metadata,
                                    media_body=media,
                                    fields='id').execute()
print 'File ID: %s' % file.get('id')
like image 142
Gurupad Hegde Avatar answered Sep 23 '22 22:09

Gurupad Hegde


I had the same problem and stumbled over this issue. Here is the code I came up with:

import os

from pydrive2.auth import GoogleAuth
from pydrive2.drive import GoogleDriv

class GoogleDriveConnection:

    _gauth = None
    _drive = None

    @staticmethod
    def get() -> GoogleDrive:
        """
        This will return a valid google drive connection

        :return: A valid GoogleDrive connection
        """
        if GoogleDriveConnection._gauth is None or GoogleDriveConnection._drive == None:
            GoogleDriveConnection._gauth = GoogleAuth()
            GoogleDriveConnection._gauth.LoadCredentialsFile(os.path.join(os.path.dirname(__file__), "mycredentials.txt"))  # this assume you have saved your credentials, like this: gauth.SaveCredentialsFile("mycredentials.txt")
            GoogleDriveConnection._drive = GoogleDrive(GoogleDriveConnection._gauth)
        return GoogleDriveConnection._drive

    @staticmethod
    def upload_image(image_path: str, folder_path: str) -> str:
        """
        Uploads an image to the google drive, and returns the https path to it

        :param image_path: Path to the image, has to end in an image type else the type won't be guessed correctly
        :param folder_path: The folder path it should have in the google drive (to structure the data there)
        :return: The https path to the uploaded image file, will be empty if the image_path is invalid
        """
        if os.path.exists(image_path):
            google_drive = GoogleDriveConnection.get()
            image = google_drive.CreateFile()
            image.SetContentFile(image_path)  # load local file data into the File instance
            # to remove the path from the filename
            image["title"] = os.path.basename(image_path)
            if folder_path:
                parent_id = GoogleDriveConnection.get_folder_id(folder_path)
                image["parents"] = [{"id": parent_id}]
            image.Upload()  # creates a file in your drive with the name
            return "https://drive.google.com/uc?id=" + str(image['id'])
        return ""

    @staticmethod
    def get_folder_id(folder_path: str, element_index=0, last_parent=None) -> str:
        """
        Gets the id of the given folder path, this function will create the folders, if they do not exist, so it will
        always return a valid id, the folder_path elements can be separated like normals via a slash.

        :param folder_path: Given folder path
        :param element_index: Element index needed for recursive creation of the element
        :param last_parent: Last parent only needed for recursive creation of the folder hierarchy
        :return: The id to the last folder in the path
        """
        folder_path_elements = folder_path.split("/")
        if len(folder_path_elements) == element_index:
            return last_parent
        folder_list = GoogleDriveConnection.get().ListFile({'q': "mimeType='application/vnd.google-apps.folder' and trashed=false"}).GetList()
        current_folder_name = folder_path_elements[element_index]
        for item in folder_list:
            if item['title'] == current_folder_name and item["parents"][0] == last_parent:
                return GoogleDriveConnection.get_folder_id(folder_path, element_index + 1, item['id'])
        # not in the list -> folder has to be created
        file_metadata = {'title': current_folder_name, 'mimeType': 'application/vnd.google-apps.folder'}
        if last_parent is not None:
            file_metadata['parents'] = [{"id": last_parent}]
        new_folder = GoogleDriveConnection.get().CreateFile(file_metadata)
        new_folder.Upload()
        return GoogleDriveConnection.get_folder_id(folder_path, element_index + 1, new_folder["id"])

This enables you to load up images to Google drive and if you call get_folder_id it will give you the id of that folder, if the folder does not exist it will be created.

like image 22
M. Denninger Avatar answered Sep 25 '22 22:09

M. Denninger