How to perform resumable file upload to Google Drive with python

|▌冷眼眸甩不掉的悲伤 提交于 2021-01-28 12:00:52

问题


I am trying to upload large files (greater than 5 MB) to Google Drive. Based Google's documentation, I would need to setup a resumable upload session. If the session is started successfully, you will get a response with a session URI. Then send another request to the URI with what I presume is your file.

I have been able to successfully set up the resumable session but I am unclear where you specify the location of your file for uploading with this method. Please see my code below.

What Google wants to start Resumable Upload

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"
}

How I did it in 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'])

A successful response location URI

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

PUT Request Google wants

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]

PUT request in python - This is where I start to get lost

uri = response.headers['Location']

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

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

I would like to know how to complete this PUT request with the path to my file and any other information that is needed. Thanks for the help.


回答1:


You almost have it done, just a couple of things:

Regarding the payload of the first request where you initiate the resumable upload and send the metadata:

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

You should put it this way to store the file in the selected folder:

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

The only change would be using the quotation marks ("") inside the brackets for each parent folder id, this is because the API is expecting an array of strings for the parents field (each string for each parent folder id) [1].

For the second part of the resumable upload (uploading the file), you just have to obtain the file you want to upload and send it as the request body with the "data" parameter in the request like this:

  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)

Using the function open() [2] with the file path including the filename (relative or absolute) and using "rb" as the 2nd parameter to read the file in binary mode, you will get a raw binary file (file object) and applying the read() [3] function to it you will get the binary data, which is what the request is expecting in the request body (data parameter).

I tested the code provided above uploading an image to a specific folder and it worked. Remember to change the content-type.

[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



来源:https://stackoverflow.com/questions/56780331/how-to-perform-resumable-file-upload-to-google-drive-with-python

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!