使用服务帐户凭据的GDrive导出失败并显示404 [英] GDrive export using Service Account creds fails with 404
问题描述
我有一个脚本可以使用OAuth客户端从GDrive文件中导出文本,效果很好-
I have a script to export text from a GDrive file using an OAuth client, which works perfectly well -
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流程是一件很痛苦的事情,由于只有我使用脚本,所以我想简化事情并改用服务帐户,而后继这篇文章-
But it's a pain to have to go through the OAuth flow every time, and since it's only me using the script I want to simplify things and use a Service Account instead, following on from this post -
我执行相同操作的新服务帐户脚本如下-
My new Service Account script, doing exactly the same thing, is as follows -
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
运行它时,得到以下内容-
but when I run it for the same id
, I get the following -
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版本将其很好地获取:/
It feels like the Service Account script is passing the authentication step (ie Service Account creds are okay) but then failing when trying to fetch the file - weird as I can fetch it fine using the OAuth version :/
对于OAuth客户端版本显然适用于同一id
的情况,对于在服务帐户版本中导致此404错误的原因,有何想法?
Any thoughts on what might be causing this 404 error in the Service Account version, given the OAuth client version clearly works for the same id
?
TIA.
推荐答案
答案:
您需要与服务帐户共享文件.
与处理任何文件一样,您需要授予用户显式权限才能查看该文件.对于您来说,服务帐户是一个独立的实体,这对他们也同样适用.
As you would with any file, you need to give a user explicit permissions to be able to see it. As a service account is a separate entitiy to you, this goes for them as well.
使用文件共享设置(您可以在Drive UI中通过右键单击文件并单击Share
来执行此操作),为服务帐户的电子邮件地址提供正确的权限(读/写).服务帐户的电子邮件地址的格式为:
Using the file sharing settings (you can just do this in the Drive UI by right-clicking the file and hitting Share
), give the email address of the service account the correct permission (read/write). The email address of the service account is in the form:
service-account-name@project-id.iam.gserviceaccount.com
希望对您有帮助!
这篇关于使用服务帐户凭据的GDrive导出失败并显示404的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!