簡體   English   中英

如何使用 Python 和 Drive API v3 將文件上傳到 Google Drive

[英]How to upload a file to Google Drive using Python and the Drive API v3

我曾嘗試使用 Python 腳本將文件從本地系統上傳到 Google Drive,但我不斷收到 HttpError 403。腳本如下:

from googleapiclient.http import MediaFileUpload
from googleapiclient import discovery
import httplib2
import auth

SCOPES = "https://www.googleapis.com/auth/drive"
CLIENT_SECRET_FILE = "client_secret.json"
APPLICATION_NAME = "test"
authInst = auth.auth(SCOPES, CLIENT_SECRET_FILE, APPLICATION_NAME)
credentials = authInst.getCredentials()
http = credentials.authorize(httplib2.Http())
drive_serivce = discovery.build('drive', 'v3', credentials=credentials)
file_metadata = {'name': 'gb1.png'}
media = MediaFileUpload('./gb.png',
                        mimetype='image/png')
file = drive_serivce.files().create(body=file_metadata,
                                    media_body=media,
                                    fields='id').execute()
print('File ID: %s' % file.get('id'))

錯誤是:

googleapiclient.errors.HttpError: <HttpError 403 when requesting
https://www.googleapis.com/upload/drive/v3/files?uploadType=multipart&alt=json&fields=id 
returned "Insufficient Permission: Request had insufficient authentication scopes.">

我在代碼中使用了正確的范圍還是遺漏了什么?

我還嘗試了我在網上找到的一個腳本,它運行良好,但問題是它需要一個靜態令牌,它會在一段時間后過期。 那么如何動態刷新令牌呢?

這是我的代碼:

import json
import requests
headers = {
    "Authorization": "Bearer TOKEN"}
para = {
    "name": "account.csv",
    "parents": ["FOLDER_ID"]
}
files = {
    'data': ('metadata', json.dumps(para), 'application/json; charset=UTF-8'),
    'file': ('mimeType', open("./test.csv", "rb"))
}
r = requests.post(
    "https://www.googleapis.com/upload/drive/v3/files?uploadType=multipart",
    headers=headers,
    files=files
)
print(r.text)

“權限不足:請求的身份驗證范圍不足。”

意味着您進行身份驗證的用戶尚未授予您的應用程序權限來執行您嘗試執行的操作。

files.create方法要求您使用以下范圍之一對用戶進行身份驗證。

在此處輸入圖片說明

而您的代碼似乎確實使用了完整的驅動范圍。 我懷疑發生的情況是您已經對您的用戶進行了身份驗證,然后更改了代碼中的范圍,並且沒有促使用戶再次登錄並授予同意。 您需要通過讓用戶直接在他們的 Google 帳戶中將其刪除或僅刪除您存儲在您的應用程序中的憑據來從您的應用程序中刪除用戶同意。 這將強制用戶再次登錄。

谷歌登錄還有一個批准提示強制選項,但我不是python開發者,所以我不確定如何強制執行。 它應該類似於下面的 prompt='consent' 行。

flow = OAuth2WebServerFlow(client_id=CLIENT_ID,
                           client_secret=CLIENT_SECRET,
                           scope='https://spreadsheets.google.com/feeds '+
                           'https://docs.google.com/feeds',
                           redirect_uri='http://example.com/auth_return',
                           prompt='consent')

同意屏幕

如果操作正確,用戶應該會看到這樣的屏幕

在此處輸入圖片說明

提示他們授予您對其雲端硬盤帳戶的完全訪問權限

令牌泡菜

如果您在https://developers.google.com/drive/api/v3/quickstart/python上關注 googles 教程,您需要刪除包含用戶存儲同意的 token.pickle。

if os.path.exists('token.pickle'):
    with open('token.pickle', 'rb') as token:
        creds = pickle.load(token)

回答:

刪除您的token.pickle文件並重新運行您的應用程序。

更多信息:

只要您擁有正確的憑據集,那么更新應用程序范圍時所需的一切就是重新獲取令牌。 刪除位於應用程序根文件夾中的令牌文件,然后再次運行該應用程序。 如果您擁有https://www.googleapis.com/auth/drive范圍,並且在開發者控制台中啟用了 Gmail API,那么您應該沒問題。

參考:

您可以使用google-api-python-client構建Drive 服務以使用Drive API

  • 按照此答案的前 10 個步驟獲取您的授權。
  • 如果您希望用戶僅通過一次同意屏幕,則將憑據存儲在文件中。 它們包括一個刷新令牌,應用程序可使用該令牌在過期后請求授權 例子

使用有效的驅動器服務,您可以通過調用類似以下的函數來上傳文件upload_file

def upload_file(drive_service, filename, mimetype, upload_filename, resumable=True, chunksize=262144):
    media = MediaFileUpload(filename, mimetype=mimetype, resumable=resumable, chunksize=chunksize)
    # Add all the writable properties you want the file to have in the body!
    body = {"name": upload_filename} 
    request = drive_service.files().create(body=body, media_body=media).execute()
    if getFileByteSize(filename) > chunksize:
        response = None
        while response is None:
            chunk = request.next_chunk()
            if chunk:
                status, response = chunk
                if status:
                    print("Uploaded %d%%." % int(status.progress() * 100))
    print("Upload Complete!")

現在傳入參數並調用函數...

# Upload file
upload_file(drive_service, 'my_local_image.png', 'image/png', 'my_imageination.png' )

您將在 Google Drive 根文件夾中看到名稱為my_imageination.png 的文件。

在此處詳細了解 Drive API v3 服務和可用方法。


getFileSize()函數:

def getFileByteSize(filename):
    # Get file size in python
    from os import stat
    file_stats = stat(filename)
    print('File Size in Bytes is {}'.format(file_stats.st_size))
    return file_stats.st_size

上傳到驅動器中的某些文件夾很容易...

只需在請求正文中添加父文件夾 ID。

這是File屬性 文件的父母 [] 屬性

例子:

request_body = {
  "name": "getting_creative_now.png",
  "parents": ['myFiRsTPaRentFolderId',
              'MyOtherParentId',
              'IcanTgetEnoughParentsId'],
}

要使用范圍“https://www.googleapis.com/auth/drive”,您需要提交谷歌應用程序進行驗證。

查找范圍的圖像

因此,請使用范圍“https://www.googleapis.com/auth/drive.file”而不是“https://www.googleapis.com/auth/drive”來上傳文件而無需驗證。

還可以使用 SCOPE 作為列表。

例如: SCOPES = ['https://www.googleapis.com/auth/drive.file']

我可以使用上述 SCOPE 成功上傳和下載文件到谷歌驅動器。

我找到了將文件上傳到谷歌驅動器的解決方案。 這里是:

import requests
import json
url = "https://www.googleapis.com/oauth2/v4/token"

        payload = "{\n\"" \
                  "client_id\": \"CLIENT_ID" \
                  "\",\n\"" \
                  "client_secret\": \"CLIENT SECRET" \
                  "\",\n\"" \
                  "refresh_token\": \"REFRESH TOKEN" \
                  "\",\n\"" \
                  "grant_type\": \"refresh_token\"\n" \
                  "}"
        headers = {
            'grant_type': 'authorization_code',
            'Content-Type': 'application/json'
        }

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

        res = json.loads(response.text.encode('utf8'))


        headers = {
            "Authorization": "Bearer %s" % res['access_token']
        }
        para = {
            "name": "file_path",
            "parents": "google_drive_folder_id"
        }
        files = {
            'data': ('metadata', json.dumps(para), 'application/json; charset=UTF-8'),
            # 'file': open("./gb.png", "rb")
            'file': ('mimeType', open("file_path", "rb"))
        }
        r = requests.post(
            "https://www.googleapis.com/upload/drive/v3/files?uploadType=multipart",
            headers=headers,
            files=files
        )
        print(r.text)

要生成客戶端 ID、客戶端密鑰和刷新令牌,您可以點擊以下鏈接:- 單擊此處

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM