繁体   English   中英

Python-如何使用 Google Drive API 将文件上传到一个文件夹?

[英]Python- How to upload files to one folder using Google Drive API?

使用 Google Drive API,我正在尝试将文件上传到 Google Drive。

请看下面的代码。 该代码成功运行,但不是将所有文件上传到一个文件夹,而是为它上传的每个文件创建单独的文件夹。

我相信我在代码中的这一行出错了: q="name='" + folder + "' and tramed=false and mimeType = 'application/vnd.google-apps.folder' and '{0}' in parents".format(parent_folder_id) 但无法弄清楚。 非常感谢任何帮助。

def uploadFile(service,pathname, mimetype, folder_id,replace):
    # Check if the file exists on google drive
    filename=os.path.split(pathname)[1]
    page_token = None
    q="name='" + filename + "' and trashed=false  and '{0}' in parents".format(folder_id)
    try:
        response = service.files().list(q= q, spaces='drive',
                                          fields="files(name, id)",
                                          pageToken=page_token).execute()
        if replace==True:
            file_id=response.get('files')[1]['id']
            file = service.files().get(fileId=file_id).execute()
             # File's new content.
            media_body = MediaFileUpload(pathname, resumable=True)
             # Send the request to the API.
            updated_file = service.files().update(
                fileId=file_id,
                body=file,
                newRevision=False,
                media_body=media_body).execute()
    except:
        file_metadata = {'name': filename, "parents": [folder_id]}
        media = MediaFileUpload(pathname,
                                mimetype=mimetype)
        file = service.files().create(body=file_metadata,

                                      media_body=media,
                                      fields='id').execute()
#################################
def UploadFiles(inifile, filespec, parent_folder):
    page_token = None
    # Retrieve the parent folder id from the parent folder name
    q="name='" + parent_folder + "' and trashed=false and mimeType = 'application/vnd.google-apps.folder'"
    try:
        response = service.files().list(q=q, spaces='drive',fields="files(name,id)",pageToken=page_token).execute()
    except:
        print("Parent folder",parent_folder,"was not found")
        return
    parent_folder_id = response.get('files')[0]['id']
    ##For loop to go through each file in filelist to upload
    for pathname in glob.glob(filespec):
    #for files in file_list:
        folder=pathname.split('_')[1]
        # Check if the folder exists
        q="name='" + folder + "' and trashed=false and mimeType = 'application/vnd.google-apps.folder' and '{0}' in parents".format(parent_folder_id)
        try:
            response = service.files().list(q=q, spaces='drive',fields="files(name,id,parent_id)").execute()
            folder_id = response.get('files')[0]['id']
        except:
            #if folder doesnt exist, create and upload
            file_metadata = {'name': folder,'mimeType':'application/vnd.google-apps.folder','parents':[parent_folder_id]}
            #createFolder(folder)
            new_folder = service.files().create(body=file_metadata, fields='id').execute()
            folder_id = new_folder.get('id')
        # Now upload the file!
        if pathname.endswith("pdf"):
            mimetype = 'application/pdf'
        else:
            mimetype = 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'
        #print("uploading file ",files," path",filepath," filename",filename, " folderid", folderid)
        uploadFile(service,pathname,mimetype,folder_id,True)

我不是 python 开发人员,因此您可能需要稍微处理一下代码。

您的搜索有问题

#Check if the folder exists
q="name='" + folder + "' and trashed=false and mimeType = 'application/vnd.google-apps.folder' and '{0}' in parents".format(parent_folder_id)

正确的格式是parents in 'ParentFolderId'应该给你。

q="name='" + folder + "' and trashed=false and mimeType = 'application/vnd.google-apps.folder' and parents in '{0}' in ".format(parent_folder_id)

另请记住,如果您想更新现有文件用户 files().update,则每次调用 service.files().create 都会创建一个新文件

我在一个项目中遇到了类似的问题,我已经对其进行了调整,以满足您使用以下虚拟数据上传 Google Drive 的需求:

from googleapiclient import discovery
from googleapiclient.http import MediaFileUpload, MediaIoBaseDownload
from httplib2 import Http
from oauth2client import file, client, tools
from pathlib import Path
import datetime

def gDriveFolder(service, name: str):
        Drive_service = service

        #Check if GDrive folder exists
        folder_metadata = {
            'name': name,
            'mimeType': 'application/vnd.google-apps.folder'
        }
        query = "name contains '{}' and mimeType='{}' and trashed=false".format(folder_metadata["name"],folder_metadata["mimeType"])
        response = Drive_service.files().list(q=query, pageSize=100, fields="nextPageToken, files(id, name, mimeType, size, parents, modifiedTime)").execute().get('files', [])
        if response.__len__() == 1 and response[0].get("name") == folder_metadata["name"]:
            folder_id = response[0].get("id")
        else:
            #creates GDrive folder
            gfolder = Drive_service.files().create(body=folder_metadata,
                                            fields='id').execute()
            folder_id = gfolder.get('id')
        
        return folder_id


def gDriveFolderFilesQuery(service, folder_name_for_q : str):
    Drive_service = service
    folder_id = gDriveFolder(Drive_service, folder_name_for_q)
    folder_query = "'%s' in parents" % folder_id 
    files_response = Drive_service.files().list(q=folder_query, pageSize=100, fields="nextPageToken, files(id, name, mimeType, size, parents, modifiedTime)").execute().get('files', [])
    file_names = dict()
    for log_file in files_response:
        file_names[log_file.get("name")] = log_file.get("id")
    return file_names

def uploadFile(service, pathname, mimetype_v, folder_id, folder_name_for_q, replace):
        Drive_service = service

        file_names = gDriveFolderFilesQuery(Drive_service, folder_name_for_q)

        dummy_file_path = Path(pathname)
        file_name = pathname.name
        
        if not mimetype_v:
            mimetype_v = 'text/plain'
        
        if replace:
            file_metadata = {
                'name': file_name,
                'mimeType': 'application/vnd.google-apps.script',
                'parents':[folder_id]
            }
            media = MediaFileUpload(dummy_file_path,
                                    mimetype=mimetype_v,
                                    resumable=True)
            file = Drive_service.files().create(body=file_metadata,
                                                media_body=media,
                                                fields='id').execute()

        #checks if the text.txt exists
        if file_name in list(file_names.keys()):
            file_id = file_names[file_name]
            media = MediaFileUpload(dummy_file_path,
                                    mimetype=mimetype_v,
                                    resumable=True)
            file = Drive_service.files().update(fileId=file_id,body=None,
                                                media_body=media).execute()

        else:
            file_metadata = {
                'name': file_name,
                'mimeType': 'application/vnd.google-apps.script',
                'parents':[folder_id]
            }
            media = MediaFileUpload(dummy_file_path,
                                    mimetype=mimetype_v,
                                    resumable=True)
            file = Drive_service.files().create(body=file_metadata,
                                                media_body=media,
                                                fields='id').execute()

def uploadFiles(service, DirectoryFolder, mimetype_v, folder_id, folder_name_for_q, replace):

    for a_file in DirectoryFolder.glob("*"):
        if a_file.is_dir():
            continue
        uploadFile(service, a_file, mimetype_v, folder_id, folder_name_for_q, replace)



if __name__ == "__main__":
    
    SCOPES = ['https://www.googleapis.com/auth/drive', 
                        'https://www.googleapis.com/auth/drive.file', 
                        'https://www.googleapis.com/auth/drive.appdata',
                        'https://www.googleapis.com/auth/drive.metadata', 
                        'https://www.googleapis.com/auth/drive.activity']


    store = file.Storage('storage.json')
    creds = store.get()
    if not creds or creds.invalid:
        flow = client.flow_from_clientsecrets('client.json', SCOPES)
        creds = tools.run_flow(flow, store)
    DRIVE = discovery.build('drive', 'v3', http=creds.authorize(Http())) #be prepared to be authorized

    #make a dummy folder
    dummy_file_directory = Path("dummy/")
    dummy_file_directory.mkdir(parents=True, exist_ok=True)

    #create a set list of dummy files
    how_many_files = 5
    for i in range(how_many_files+1):
        dummy_file = dummy_file_directory / ("test_num_%s.txt" % i)
        data = "current date and time for iteration %s is %s" % (i, datetime.datetime.now())
        with open(str(dummy_file), "w", encoding='utf-8') as f:
            f.write(data) 

    folder_name_for_q = "folder_for_priya"
    folder_id = gDriveFolder(DRIVE, folder_name_for_q)

    mimetype_v = 'text/plain'
    uploadFiles(DRIVE, dummy_file_directory, mimetype_v, folder_id, folder_name_for_q, replace=False)

我会尽我所能快速简要介绍正在发生的事情。 运行主程序,声明凭据和范围。 (此授权方法改编自以下指南

接下来创建一个虚拟文件夹,然后使用datetime模块填充虚拟文件(在本例中为 5 个文本文件)及其各自的迭代和时间戳。

之后,定义了一个新变量来给出要在谷歌驱动器上的文件夹的名称。

gDriveFolder方法检查这样的 GoogleDrive 目录是否已经存在。 无论是否存在这样的文件夹,都会返回该文件夹的文件夹 ID。

接下来调用uploadFiles方法,它采用pathlib.Path object 在其中传递,并遍历它检测到的可能不是文件夹的文件。 对于文件夹dummy_file_directory中的每个文件,都会执行方法uploadFile

最后, uploadFile获取文件及其各自的 mimetype,并通过首先调用gDriveFolderFilesQuery方法检查此类文件是否存在,并验证上传文件是否已在 GoogleDrive 目录中。

希望演练足够简单,可以实现您想要的实现。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM