首页 > 解决方案 > 如何使用 python 执行可恢复的文件上传到 Google Drive

问题描述

我正在尝试将大文件(大于 5 MB)上传到 Google Drive。基于谷歌的文档,我需要设置一个可恢复的上传会话。如果会话成功启动,您将收到带有会话 URI 的响应。然后使用我认为是您的文件向 URI 发送另一个请求。

我已经能够成功设置可恢复会话,但我不清楚您指定文件的位置以使用此方法上传。请在下面查看我的代码。

Google 想要启动可恢复上传的内容

POST https://www.googleapis.com/upload/drive/v3/files?uploadType=resumable HTTP/1.1
Authorization: Bearer [YOUR_AUTH_TOKEN]
Content-Length: 38
Content-Type: application/json; charset=UTF-8
X-Upload-Content-Type: application/octet-stream

{
  "name": "myObject"
}

我是如何在 Python 中做到的

import requests
from oauth2client.service_account import ServiceAccountCredentials

credentials = ServiceAccountCredentials.from_json_keyfile_dict(
    keyfile_dict=[SERVICE_ACCOUNT_JSON],
    scopes='https://www.googleapis.com/auth/drive')

delegated_credentials = credentials.create_delegated([EMAIL_ADDRESS])

access_token = delegated_credentials.get_access_token().access_token

url = "https://www.googleapis.com/upload/drive/v3/files"

querystring = {"uploadType": "resumable"}

payload = '{"name": "myObject", "parents": "[PARENT_FOLDER]"}'
headers = {
    'Content-Length': "38",
    'Content-Type': "application/json",
    'X-Upload-Content-Type': "application/octet-stream",
    'Authorization': "Bearer " + access_token
    }

response = requests.request(
    "POST", url, data=payload, headers=headers, params=querystring)

print(response.headers['Location'])

成功的响应位置 URI

https://www.googleapis.com/upload/drive/v3/files?uploadType=resumable&upload_id=[SOME_LONG_ID]

Google 想要的 PUT 请求

PUT https://www.googleapis.com/upload/drive/v3/files?uploadType=resumable&upload_id=[SOME_LONG_ID] HTTP/1.1
Content-Length: 2000000
Content-Type: application/octet-stream

[BYTES 0-1999999]

python中的PUT请求-这是我开始迷路的地方

uri = response.headers['Location']

headers = {
    'Content-Length': "2000000",
    'Content-Type': "application/json"
    }

response = requests.request(
    "PUT", uri, headers=headers)

我想知道如何使用我的文件的路径和所需的任何其他信息来完成此 PUT 请求。谢谢您的帮助。

标签: pythonfile-uploadgoogle-drive-api

解决方案


你几乎已经完成了,只有几件事:

关于您启动可恢复上传并发送元数据的第一个请求的有效负载:

payload = '{"name": "myObject", "parents": "[PARENT_FOLDER]"}'

您应该以这种方式将文件存储在所选文件夹中:

payload = '{"name": "myObject2", "parents": ["PARENT_FOLDER_ID"]}'

唯一的变化是在每个父文件夹 id 的括号内使用引号 (""),这是因为 API 期望父字段的字符串数组(每个父文件夹 id 的每个字符串)[1]。

对于可恢复上传的第二部分(上传文件),您只需获取要上传的文件并将其作为请求正文发送,请求中带有“data”参数,如下所示:

  uri = response.headers['Location']

    headers = {
        'Content-Length': "2000000",
        'Content-Type': "image/jpeg"  
    }

    #Open the file and stored it in data2
    in_file = open("filepath to the file", "rb")  # opening for [r]eading as [b]inary
    data2 = in_file.read()

    #Send the file in the request
    response = requests.request(
        "PUT", uri, data=data2, headers=headers)

使用包含文件名(相对或绝对)的文件路径的函数 open() [2] 并使用“rb”作为第二个参数以二进制模式读取文件,您将得到一个原始二进制文件(文件对象)和对其应用 read() [3] 函数,您将获得二进制数据,这是请求在请求正文(数据参数)中所期望的。

我测试了上面提供的将图像上传到特定文件夹的代码并且它有效。请记住更改内容类型。

[1] https://developers.google.com/drive/api/v3/reference/files

[2] https://docs.python.org/3/library/functions.html#open

[3] https://www.w3schools.com/python/python_file_open.asp


推荐阅读