我已经按照谷歌提供的快速入门来使用Python,并且我已经使用了谷歌提供的适当范围从驱动器 https://www.googleapis.com/auth/drive.readonly 下载文件,但我不断收到以下错误:
googleapiclient.errors.HttpError: https://www.googleapis.com/drive/v3/files/1RWpLGCWldcJyVqa0tIVlScg60ExEtcNIvJ7R9M8DuhM?alt=media 返回"只能下载包含二进制内容的文件。使用导出 与谷歌文档文件。
当我尝试运行代码下载文件时。
我可以读取驱动器上的文件,但尽管我尽了最大努力,但我似乎无法从驱动器下载特定的电子表格。以下是我的代码(编辑的文件路径和一些注释(,用于通过 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 或任何其他凭据,但如果您需要更多信息,请告诉我!
- 您想使用 google-api-python-client 和 python 下载 Google 文档(在您的情况下,它是电子表格(。
- 您想知道
Only files with binary content can be downloaded. Use Export with Google Docs files.
错误的原因 - 您已经能够使用云端硬盘 API。
如果我的理解是正确的,那么这个答案呢?
修改点:
- 当通过
get_media
方法下载Google文档文件时,会发生此类错误。- 对于
get_media
方法,可以下载除Google文档(电子表格,文档,幻灯片等(以外的文件。
- 对于
- 当您想下载Google文档文件时,请使用
export_media
方法。- 在这种情况下,由于谷歌端的规范,无法下载原始的谷歌文档。因此,请将其转换为其他格式。例如,在电子表格的情况下,它是Excel格式,CSV格式等。
修改后的脚本:
为了避免这个问题,下面修改一下怎么样?
从: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')
- 在这种情况下,谷歌电子表格将下载为Excel文件。如果要下载为CSV,请将mimeType修改为
text/csv
。
注意:
- 在这种情况下,它假设您要下载的Google文档文件是您的或公开共享的。
引用:
- 下载文件
- 文件:获取
- 文件:导出
如果我误解了你的问题,这不是你想要的方向,我很抱歉。
添加:
关于更改访问令牌范围的方法,请重命名或删除脚本中的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