[英]Google Drive API with Python not allowing file download despite correct scopes being added
我遵循了 Google 提供的使用 Python 的快速入门,并且我使用了 Google 提供的适当范围从驱动器https://www.googleapis.com/auth/drive.readonly下载文件,但我不断收到错误:
googleapiclient.errors.HttpError: https://www.googleapis.com/drive/v3/files/1RWpLGCWldcJyVqa0tIVlScg60ExEtcNIvJ7R9M8DuhM?alt=media 返回“只能下载包含二进制内容的文件。使用 Google Docs 文件导出。”
当我尝试运行代码来下载文件时。
我可以读取驱动器上的文件,但尽管我尽了最大的努力,但我似乎无法从驱动器下载特定的电子表格。 下面是我用于通过 API 建立连接的代码(已编辑的文件路径和一些注释):
def gsuite_connect(): file_path = 'OMITTED/Loading' # Get what permissions the user (using the API) will need. This as been set to high level # access by default scopes = ['https://www.googleapis.com/auth/drive.readonly'] # Access the tokens for G Suite to access the Drive. Ensure that if this file previous exists, # that it is in the current working directory store = file.Storage(os.path.join(file_path, 'storage.json')) # Access the credentials for the Drive API creds = store.get() if not creds or creds.invalid: print("\\nUsing credentials found in client_id(secret).json") flow = client.flow_from_clientsecrets(os.path.join(file_path, 'client_id.json'), scopes) creds = tools.run_flow(flow, store) http = creds.authorize(Http()) drive = discovery.build('drive', 'v3', http=http) sheets = discovery.build('sheets', 'v4', http=http) return drive, sheets
这是我用于根据Google 提供的内容下载文件的功能(已编辑的文件路径和一些评论):
def get_datalog(self): dir_path = 'OMITTED/Downloads' fname = "'FILENAME'" files = self.drive.files().list(q="name = {}".format(fname), fields="nextPageToken, files(id, name)").execute() items = files.get('files', []) # Error checking and subsequent downloading if file successfully found if not items: exit() else: # Change into the desired directory for storing the file and download file based on the # retrieved ID os.chdir(dir_path) file_id = items[0]['id'] # Request download service request = self.drive.files().get_media(fileId=file_id) fh = io.FileIO(fname, mode='w') downloader = MediaIoBaseDownload(fh, request) done = False while done is False: status, done = downloader.next_chunk() print("Download %d%%." % int(status.progress() * 100)) # Return the file path return os.path.join(dir_path, fname)
帮助将不胜感激! 我不想显示敏感文件,例如 client_id.json 或任何其他凭据,但如果您需要更多信息,请告诉我!
Only files with binary content can be downloaded. Use Export with Google Docs files.
的错误原因Only files with binary content can be downloaded. Use Export with Google Docs files.
Only files with binary content can be downloaded. Use Export with Google Docs files.
如果我的理解是正确的,这个答案怎么样?
get_media
方法下载Google Docs 文件时,会发生此类错误。
get_media
方法的情况下,可以下载 Google Docs 以外的文件(电子表格、文档、幻灯片等)。export_media
方法。
为了避免这个问题,下面的修改怎么样?
从: request = self.drive.files().get_media(fileId=file_id)
到:
request = self.drive.files().export_media(fileId=file_id, mimeType='application/vnd.openxmlformats-officedocument.spreadsheetml.sheet')
text/csv
下载,请将 mimeType 修改为text/csv
。如果我误解了您的问题并且这不是您想要的方向,我深表歉意。
关于更改访问令牌范围的方法,请重命名或删除脚本中的storage.json
文件,然后重新运行脚本。 这样,您可以为新范围重新授权,并创建包括令牌的新文件。 您可以将访问令牌与新范围一起使用。
我正在使用它,它适用于以下库:
google-auth-oauthlib==0.4.1
google-api-python-client
google-auth-httplib2
这是我正在使用的片段:
from apiclient import errors
from googleapiclient.http import MediaIoBaseDownload
from googleapiclient.discovery import build
def download_google_document_from_drive(self, file_id):
try:
request = self.service.files().get_media(fileId=file_id)
fh = io.BytesIO()
downloader = MediaIoBaseDownload(fh, request)
done = False
while done is False:
status, done = downloader.next_chunk()
print('Download %d%%.' % int(status.progress() * 100))
return fh
except Exception as e:
print('Error downloading file from Google Drive: %s' % e)
您可以将文件流写入文件:
import xlrd
workbook = xlrd.open_workbook(file_contents=fh.getvalue())
至于范围,我使用以下片段:
def __init__(self):
self.service = build('drive', 'v3',
credentials=self._service_account_credentials())
def _service_account_credentials(self.):
service_account_key_path = os.getenv('GOOGLE_APPLICATION_CREDENTIALS')
credentials = service_account.Credentials.from_service_account_file(
service_account_key_path)
scoped_credentials = credentials.with_scopes(
['https://www.googleapis.com/oauth2/v4/token'])
signer_email = scoped_credentials.service_account_email
signer = scoped_credentials.signer
credentials = google.oauth2.service_account.Credentials(
signer,
signer_email,
token_uri='https://www.googleapis.com/oauth2/v4/token'
)
return credentials
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.