首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >如何使用Python和Drive API v3将文件上传到Google Drive

如何使用Python和Drive API v3将文件上传到Google Drive
EN

Stack Overflow用户
提问于 2020-02-12 15:02:07
回答 6查看 4.7K关注 0票数 0

我尝试过使用Python脚本从本地系统上传文件到Google Drive,但我一直收到HttpError 403。脚本如下:

代码语言:javascript
运行
复制
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'))

错误是:

代码语言:javascript
运行
复制
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.">

我是否在代码中使用了正确的作用域,或者遗漏了什么?

我还尝试了我在网上找到的一个脚本,它工作得很好,但问题是它需要一个静态令牌,该令牌会在一段时间后过期。那么,如何动态刷新令牌呢?

下面是我的代码:

代码语言:javascript
运行
复制
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)
EN

回答 6

Stack Overflow用户

发布于 2020-02-12 15:35:06

“权限不足:请求的身份验证范围不足。”

意味着您已进行身份验证的用户没有授予您的应用程序执行您正在尝试执行的操作的权限。

files.create方法要求您已使用以下作用域之一对用户进行身份验证。

而您的代码似乎正在使用完整的驱动器作用域。我怀疑发生的情况是,您已经对用户进行了身份验证,然后更改了代码中的作用域,并且没有促使用户再次登录并授予同意。你需要从你的应用程序中删除用户的同意,要么让他们直接在他们的google账户中删除它,要么只是删除你在应用程序中存储的凭据。这将强制用户再次登录。

google登录也有一个批准提示强制选项,但我不是python开发人员,所以我不太确定如何强制执行。它应该类似于下面的提示=‘同意’行。

代码语言:javascript
运行
复制
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,你需要删除包含用户存储同意的token.pickle。

代码语言:javascript
运行
复制
if os.path.exists('token.pickle'):
    with open('token.pickle', 'rb') as token:
        creds = pickle.load(token)
票数 0
EN

Stack Overflow用户

发布于 2020-02-12 18:44:06

答案:

删除token.pickle文件并重新运行应用程序。

更多信息:

只要您拥有正确的凭据集,那么当您更新应用程序的作用域时,所有需要做的就是重新获取一个令牌。删除位于应用程序根文件夹中的令牌文件,然后再次运行应用程序。如果您在开发人员控制台中启用了https://www.googleapis.com/auth/drive scope、 Gmail API,那么您应该很不错。

参考文献:

票数 0
EN

Stack Overflow用户

发布于 2020-02-14 00:01:36

您可以使用google-api-python-client构建驱动器服务,以便使用Drive API

按照this answer.

  • If的前10个步骤获取您的授权,因为您希望用户只通过同意屏幕一次,然后在文件中store凭据。其中包括一个刷新令牌,应用程序可使用该令牌在expired.

之后请求授权

使用有效的驱动器服务,您可以通过调用类似以下upload_file的函数来上传文件

代码语言:javascript
运行
复制
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!")

现在传入参数并调用函数...

代码语言:javascript
运行
复制
# Upload file
upload_file(drive_service, 'my_local_image.png', 'image/png', 'my_imageination.png' )

您将在Google Drive根文件夹中看到名为:my_imageination.png的文件。

有关Drive API v3服务和可用方法here的更多信息。

getFileSize()函数:

代码语言:javascript
运行
复制
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即可。

这是properties of a File

示例:

代码语言:javascript
运行
复制
request_body = {
  "name": "getting_creative_now.png",
  "parents": ['myFiRsTPaRentFolderId',
              'MyOtherParentId',
              'IcanTgetEnoughParentsId'],
}
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/60182791

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档