[英]How to upload a file to Google Drive using Python and the Drive API v3
I have tried uploading file to Google Drive from my local system using a Python script but I keep getting HttpError 403. The script is as follows:我曾尝试使用 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'))
The error is :错误是:
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.">
Am I using the right scope in the code or missing anything ?我在代码中使用了正确的范围还是遗漏了什么?
I also tried a script I found online and it is working fine but the issue is that it takes a static token, which expires after some time.我还尝试了我在网上找到的一个脚本,它运行良好,但问题是它需要一个静态令牌,它会在一段时间后过期。 So how can I refresh the token dynamically?
那么如何动态刷新令牌呢?
Here is my code:这是我的代码:
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)
"Insufficient Permission: Request had insufficient authentication scopes."
“权限不足:请求的身份验证范围不足。”
Means that the user you have authenticated with has not granted your application permission to do what you are trying to do.意味着您进行身份验证的用户尚未授予您的应用程序权限来执行您尝试执行的操作。
The files.create method requires that you have authenticated the user with one of the following scopes. files.create方法要求您使用以下范围之一对用户进行身份验证。
while your code does appear to be using the full on drive scope.而您的代码似乎确实使用了完整的驱动范围。 What i suspect has happens is that you have authenticated your user then changed the scope in your code and not promoted the user to login again and grant consent.
我怀疑发生的情况是您已经对您的用户进行了身份验证,然后更改了代码中的范围,并且没有促使用户再次登录并授予同意。 You need to remove the users consent from your app either by having them remove it directly in their google account or just deleteing the credeitnals you have stored in your app.
您需要通过让用户直接在他们的 Google 帐户中将其删除或仅删除您存储在您的应用程序中的凭据来从您的应用程序中删除用户同意。 This will force the user to login again.
这将强制用户再次登录。
There is also an approval prompt force option to the google login but am not a python dev so im not exactly sure how to force that.谷歌登录还有一个批准提示强制选项,但我不是python开发者,所以我不确定如何强制执行。 it should be something like the prompt='consent' line below.
它应该类似于下面的 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')
If done correctly the user should see a screen like this如果操作正确,用户应该会看到这样的屏幕
Prompting them to grant you full access to their drive account提示他们授予您对其云端硬盘帐户的完全访问权限
If you are following googles tutorial here https://developers.google.com/drive/api/v3/quickstart/python you need to delete the token.pickle that contains the users stored 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)
Delete your token.pickle
file and re-run your application.删除您的
token.pickle
文件并重新运行您的应用程序。
As long as you have the correct set of credentials then all that is required when you update the scopes of your application is to re-obtain a token.只要您拥有正确的凭据集,那么更新应用程序范围时所需的一切就是重新获取令牌。 Delete the token file located in the application's root folder, then run the application again.
删除位于应用程序根文件夹中的令牌文件,然后再次运行该应用程序。 If you have the
https://www.googleapis.com/auth/drive
scope, and the Gmail API enabled in the developer console, you should be good.如果您拥有
https://www.googleapis.com/auth/drive
范围,并且在开发者控制台中启用了 Gmail API,那么您应该没问题。
You can use the google-api-python-client to build a Drive service for using Drive API .您可以使用google-api-python-client构建Drive 服务以使用Drive API 。
With a valid Drive Service you can upload a file by calling a function like the following upload_file
:使用有效的驱动器服务,您可以通过调用类似以下的函数来上传文件
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!")
Now pass in the parameters and call the function...现在传入参数并调用函数...
# Upload file
upload_file(drive_service, 'my_local_image.png', 'image/png', 'my_imageination.png' )
You will see the file with the name: my_imageination.png in your Google Drive root folder.您将在 Google Drive 根文件夹中看到名称为my_imageination.png 的文件。
More about the Drive API v3 service and available methods here . 在此处详细了解 Drive API v3 服务和可用方法。
getFileSize()
function: 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
Just add the parent folder Id(s) in the body of the request.只需在请求正文中添加父文件夹 ID。
Here are the properties of a File .这是File的属性。
request_body = {
"name": "getting_creative_now.png",
"parents": ['myFiRsTPaRentFolderId',
'MyOtherParentId',
'IcanTgetEnoughParentsId'],
}
To use the scope 'https://www.googleapis.com/auth/drive' you need to submit the google app for verification.要使用范围“https://www.googleapis.com/auth/drive”,您需要提交谷歌应用程序进行验证。
Find the image for scope查找范围的图像
So use the scope 'https://www.googleapis.com/auth/drive.file' instead of 'https://www.googleapis.com/auth/drive' to upload files without verification.因此,请使用范围“https://www.googleapis.com/auth/drive.file”而不是“https://www.googleapis.com/auth/drive”来上传文件而无需验证。
Also use SCOPES as list.还可以使用 SCOPE 作为列表。
ex: SCOPES = ['https://www.googleapis.com/auth/drive.file']
例如:
SCOPES = ['https://www.googleapis.com/auth/drive.file']
I can successfully upload and download the files to google drive by using the above SCOPE.我可以使用上述 SCOPE 成功上传和下载文件到谷歌驱动器。
I found the solution for uploading a file to google drive.我找到了将文件上传到谷歌驱动器的解决方案。 Here it is:
这里是:
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)
For generating client id, client secret and refresh token, you can follow the link :- click here要生成客户端 ID、客户端密钥和刷新令牌,您可以点击以下链接:- 单击此处
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.