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

Python-如何使用Google Drive API将文件上载到一个文件夹?,python,python-3.x,google-api,google-drive-api,google-api-python-client,Python,Python 3.x,Google Api,Google Drive Api,Google Api Python Client,使用谷歌驱动器API,我试图上传文件到谷歌驱动器 请参阅下面的代码。代码运行成功,但不是将所有文件上载到一个文件夹,而是为上载的每个文件创建单独的文件夹 我相信我在代码中的这一行出现了错误:q=“name=”“+folder+”,trashed=false,mimeType=”application/vnd.google apps.folder”和“{0}”在parents.format(parent\u folder\u id)中,但无法理解。非常感谢您的帮助 def uploadFile(s

使用谷歌驱动器API,我试图上传文件到谷歌驱动器

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

我相信我在代码中的这一行出现了错误:q=“name=”“+folder+”,trashed=false,mimeType=”application/vnd.google apps.folder”和“{0}”在parents.format(parent\u folder\u 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)
正确的格式是“ParentFolderId”中的父项
应该为您提供

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

还要记住,service.files().create将在每次调用它时创建一个新文件,如果您想更新现有的文件user files().update

我在一个项目中遇到了类似的问题,我已经对其进行了调整,以满足您使用以下虚拟数据上传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个文本文件),其中包含各自的迭代次数和时间戳

之后,定义了一个新变量,以提供要在google drive上的文件夹的名称

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

接下来调用方法
uploadFiles
,该方法获取在其中传递的
pathlib.Path
对象,并对其检测到的不可能是文件夹的文件进行迭代。对于文件夹dummy_file_目录中的每个文件,执行方法
uploadFile

最后,
uploadFile
获取文件及其各自的mimetype,首先调用
gDriveFolderFilesQuery
方法检查是否存在这样的文件,并验证上载文件是否已经在GoogleDrive目录中


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

我尝试了“{0}”中的父文件夹“.format(parent_folder_id)”中的父文件夹,但同样的问题是它会创建多个文件夹。我并不擅长Python,但我会检查从response=service.files()返回的响应(q=q,spaces='drive',fields=”execute()是否实际返回了某些内容,而您的读取错误?