如何使用 Google Drive API v3 将可恢复的上传到 Python 中的共享文件夹?

How do I do a resumable upload to a shared folder in Python using Google Drive API v3?

我正在尝试使用 Google 驱动器 API v3 和 Python 3.10.4 将文件上传到 Google 驱动器。我正在尝试进行可恢复的上传。我成功地获取了开始上传的 URI 位置,但是当我尝试将文件上传到该位置时,我从 Google.

返回了 404

原因:'notFound', 消息:'File not found: #FileIdHere', 位置类型:'parameter', 位置:'fileId'

Google 为我提供了我要上传到的文件夹的 fileId。它与我从 get_folderId 函数中获得的 ID 相同。

def backup(drive: Drive, cam_name: str):
    logger.info('Backup drive has been plugged in')
    logger.info(f'Backing up {drive.letter}')

    #Grab the folder ID of the folder we are uploading files to
    folderId = get_folderId(cam_name)
    access_token = get_access_token()

    rootDirectory = drive.letter + "\FILE\"
    if not os.path.isdir(rootDirectory):
        rootDirectory = drive.letter + "\DCIM"
    for root, dirs, files in os.walk(rootDirectory):
        for fileName in files:
            #Get file path
            filePath = os.path.join(root, fileName)

            #Grab mimetype for file
            mime = magic.Magic(mime=True)
            mimeType = mime.from_file(filePath)

            #Get size of file
            fileSize = os.path.getsize(filePath)

            #Retrieve session for resumable upload
            headers = {"Authorization": "Bearer "+access_token, "Content-Type": "application/json"}
            parameters = {
                "name": fileName,
                "mimeType": mimeType,
                "parents" : [folderId]
                
            }
            response = requests.post(
                    "https://www.googleapis.com/upload/drive/v3/files?uploadType=resumable",
                    headers=headers,
                    data=json.dumps(parameters)
            )
            #Location to upload file
            uploadLocation = response.headers['Location']

            #Upload the file
            headers = {"Content-Range": "bytes 0-" + str(fileSize - 1) + "/" + str(fileSize)}
            response = requests.put(
                uploadLocation,
                headers = headers,
                data=open(filePath, 'rb')
            )
            logger.info(response.text)

在上述函数的参数变量中,我尝试添加 supportsAllDrives = True 无济于事,所以我不确定为什么找不到文件夹。

#Gets the folder ID of the provided folder name from Google Drive
def get_folderId(cam_name: str):
    service = get_google_service()
    page_token = None
    queryString = "mimeType='application/vnd.google-apps.folder' and name='{}' and trashed = false".format(cam_name)
    response = service.files().list(q = queryString,
                                    spaces='drive',
                                    corpora='drive',
                                    supportsAllDrives=True,
                                    includeItemsFromAllDrives=True,
                                    driveId= #DriveIdGoesHere,
                                    fields='nextPageToken, files(id, name)',
                                    pageToken=page_token).execute()
    folderId = response.get('files')[0].get('id')
    return folderId
#Gets the Google service
def get_google_service():
        SCOPES = ['https://www.googleapis.com/auth/drive']
        SERVICE_ACCOUNT_FILE = 'service.json'
        credentials = service_account.Credentials.from_service_account_file(
                SERVICE_ACCOUNT_FILE, scopes=SCOPES)
        creds = credentials.with_subject(#EmailGoesHere)
        service = build('drive', 'v3', credentials=creds)

        return service

我相信你的目标如下。

  • 来自 How do I do a resumable upload to a shared folder in Python using Google Drive API v3?,我认为您可能想将文件上传到 Google 云端硬盘中的共享文件夹。
  • 从您的显示脚本来看,您似乎正在使用服务帐户。
  • 但是,根据 Google gives me the fileId of the folder I'm attempting to upload to. Its the same id I get from my get_folderId function.,在您的情况下,我认为您可能想要将文件上传到共享云端硬盘中的文件夹。

如果我的理解是正确的,从你reason: 'notFound', message: 'File not found: #FileIdHere', locationType: 'parameter', location: 'fileId'的错误信息来看,下面的修改怎么样?

发件人:

response = requests.post(
        "https://www.googleapis.com/upload/drive/v3/files?uploadType=resumable",
        headers=headers,
        data=json.dumps(parameters)
)

收件人:

response = requests.post(
        "https://www.googleapis.com/upload/drive/v3/files?uploadType=resumable&supportsAllDrives=true",
        headers=headers,
        data=json.dumps(parameters)
)
  • 当您要上传文件到共享Drive中的文件夹,并且folderId的值为共享Drive中文件夹的文件夹ID时,需要包含supportsAllDrives=true到查询参数。

注:

  • 当我使用您的 https://www.googleapis.com/upload/drive/v3/files?uploadType=resumable 端点测试您的脚本时,我确认 File not found: 的相同错误。
  • 当我使用修改后的 https://www.googleapis.com/upload/drive/v3/files?uploadType=resumable&supportsAllDrives=true 端点测试您的脚本时,我确认文件可以正确上传。
  • 但是,如果您的服务帐户没有共享驱动器的写入权限,则会出现错误。请注意这一点。

参考

希望这段代码对您有所帮助

from pydrive.auth import GoogleAuth
from pydrive.drive import GoogleDrive
from openpyxl import load_workbook
from openpyxl.drawing.image import Image as pyImage
from PIL import Image
import progressbar
import requests

def upload_as_csv(df, ver):

   title = "doc-{fver}.csv".format(fver=ver)

   path = 'output/{ftit}'.format(ftit=title)

   df.to_csv(path)

   gauth = GoogleAuth()
   drive = GoogleDrive(gauth)

   uploaded = drive.CreateFile({'title': title})
   uploaded.SetContentFile(path)
   uploaded.Upload()
   print('Uploaded file with ID {}'.format(uploaded.get('id')))
   print('Version number {}'.format(ver))

   return True