python - 使用服务帐户凭据的 GDrive 导出失败并显示 404

标签 python google-api google-drive-api google-api-python-client service-accounts

我有一个使用 OAuth 客户端从 GDrive 文件导出文本的脚本,效果非常好 -

import googleapiclient.discovery as google

from apiclient.http import MediaIoBaseDownload

from google_auth_oauthlib.flow import InstalledAppFlow

from google.auth.transport.requests import Request

import datetime, io, os, pickle

Scopes=" ".join(['https://www.googleapis.com/auth/drive.file',
                 'https://www.googleapis.com/auth/drive.metadata',
                 'https://www.googleapis.com/auth/drive.readonly'])

TokenFile="token.pickle"

def init_creds(clientfile,
               scopes,
               tokenfile=TokenFile):            
    token=None
    if os.path.exists(tokenfile):
        with open(tokenfile, 'rb') as f:
            token=pickle.load(f)            
    if (not token or
        not token.valid or
        token.expiry < datetime.datetime.utcnow()):    
        if (token and
            token.expired and
            token.refresh_token):
            token.refresh(Request())
        else:
            flow=InstalledAppFlow.from_client_secrets_file(clientfile, scopes)
            token=flow.run_local_server(port=0)
        with open(tokenfile, 'wb') as f:
            pickle.dump(token, f)
    return token

def export_text(id,
                clientfile,
                scopes=Scopes):
    creds=init_creds(clientfile=clientfile,
                     scopes=scopes)
    service=google.build('drive', 'v3', credentials=creds)
    request=service.files().export_media(fileId=id,
                                         mimeType='text/plain')
    buf=io.BytesIO()
    downloader, done = MediaIoBaseDownload(buf, request), False
    while done is False:
        status, done = downloader.next_chunk()
        destfilename="tmp/%s.txt" % id
    return buf.getvalue().decode("utf-8")

if __name__=='__main__':
    print (export_text(id="#{redacted}"
                       clientfile="/path/to/oath/client.json"))

但是每次都必须经历 OAuth 流程是很痛苦的,而且由于只有我使用脚本,我想简化事情并使用服务帐户,从这篇文章开始 -

Google Drive API Python Service Account Example

我的新服务帐户脚本执行完全相同的操作,如下 -

import googleapiclient.discovery as google

from oauth2client.service_account import ServiceAccountCredentials

from apiclient.http import MediaIoBaseDownload

import io

Scopes=" ".join(['https://www.googleapis.com/auth/drive.file',
                 'https://www.googleapis.com/auth/drive.metadata',
                 'https://www.googleapis.com/auth/drive.readonly'])

def export_text(id,
                clientfile,
                scopes=Scopes):
    creds=ServiceAccountCredentials.from_json_keyfile_name(clientfile,
                                                           scopes)
    service=google.build('drive', 'v3', credentials=creds)
    request=service.files().export_media(fileId=id,
                                         mimeType='text/plain')
    buf=io.BytesIO()
    downloader, done = MediaIoBaseDownload(buf, request), False
    while done is False:
        status, done = downloader.next_chunk()
        destfilename="tmp/%s.txt" % id
    return buf.getvalue().decode("utf-8")

if __name__=='__main__':
    print (export_text(id="#{redacted}",
                       clientfile="path/to/service/account.json"))

但是当我为相同的 id 运行它时,我得到以下结果 -

googleapiclient.errors.HttpError: <HttpError 404 when requesting https://www.googleapis.com/drive/v3/files/#{redacted}/export?mimeType=text%2Fplain&alt=media returned "File not found: #{redacted}.">

感觉服务帐户脚本正在通过身份验证步骤(即服务帐户信用没问题),但在尝试获取文件时失败 - 很奇怪,因为我可以使用 OAuth 版本很好地获取它:/

考虑到 OAuth 客户端版本显然适用于相同的 id,您对可能导致服务帐户版本中出现此 404 错误的原因有什么想法吗?

最佳答案

答案:

您需要与服务帐户共享您的文件。

更多信息:

与处理任何文件一样,您需要授予用户明确的权限才能查看它。由于服务帐户对您来说是一个单独的实体,因此这也适用于他们。

使用文件共享设置(您可以在云端硬盘用户界面中右键单击文件并点击共享来执行此操作),为服务帐户的电子邮件地址提供正确的权限(读取/写)。服务帐户的电子邮件地址的格式为:

<a href="https://stackoverflow.com/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="bbc8dec9cdd2d8de96dad8d8d4ced5cf96d5dad6defbcbc9d4d1ded8cf96d2df95d2dad695dcc8dec9cdd2d8dedad8d8d4ced5cf95d8d4d6" rel="noreferrer noopener nofollow">[email protected]</a>

关于python - 使用服务帐户凭据的 GDrive 导出失败并显示 404,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/64677744/

相关文章:

google-drive-api - 通过 google drive api 恢复视频 url,以便在 html5 播放器中流式传输视频

java - Android 应用程序中的云驱动器使用

python - 调用所有可能的函数组合

python - 如何以编程方式选择 ipyvuetify 中 TextField 的所有内容?

python - 如何使用 Python 访问(读取、写入)Google Sheets 电子表格?

google-api - 使用 Google OAuth2.0 将登录电子邮件限制为特定域名

google-apps-script - "Can' t 找到 insertSheet 函数“更新代码以使用高级 Google 服务后出现错误

python - 导入错误 : No module named PyQT5 (Win7x64)

python - 如何使用 flask-wtf 为 rest api 禁用 View 的 csrf?

python - 了解基本 Python Google API 示例