【问题标题】:google-api-python-client bug with media downloadinggoogle-api-python-client 媒体下载错误
【发布时间】:2017-06-07 15:05:44
【问题描述】:

使用google-api-python-client==1.6.2

fh = io.BytesIO()
request = self.drive_service.files().export_media(
    fileId='1fwshPVKCACXgNxJtmGN94X-9RRrukiDs9q4s-n0nGlM',
    mimeType='application/vnd.openxmlformats-officedocument.wordprocessingml.document'
)
downloader = MediaIoBaseDownload(fh, request, chunksize=1024)
done = False
while done is False:
    status, done = downloader.next_chunk()
    print "Download ", status.progress(), downloader._progress, downloader._total_size, done

输出:

Download  0.0 973060 None False
Download  0.0 1946120 None False
Download  0.0 2919180 None False
Download  0.0 3892240 None False
Download  0.0 4865300 None False
Download  0.0 5838360 None False
Download  0.0 6811420 None False
Download  0.0 7784480 None False
Download  0.0 8757540 None False
...

下载文件的文件大小为 973060 字节。因此,库忽略了chunksize 参数并且没有停止。永无止境。

那么,谁能告诉我是我的要求太高还是图书馆太差了?

【问题讨论】:

  • 奇怪。您是否尝试过下载不同大小的文件并查看行为是否仍然相同?
  • 我尝试了不同的块大小和文件。我知道chunksize 总是被忽略(一个文件在一个请求中下载)和许多其他文件没有无限循环下载。我认为这个文件类型的主要问题。它是由模板创建的 Google 文档。

标签: python google-drive-api google-api-client google-api-python-client


【解决方案1】:

下面的示例怎么样?

示例:

request = self.drive_service.files().export_media(
    fileId='1fwshPVKCACXgNxJtmGN94X-9RRrukiDs9q4s-n0nGlM',
    mimeType='application/vnd.openxmlformats-officedocument.wordprocessingml.document'
).execute()
with open('sample.docx', 'wb') as f:
    f.write(request)

如果这不起作用,我很抱歉。

【讨论】:

  • 是的。有用。谢谢你。它对我很有用,因为 Google 文档中没有这样的示例。
  • @Alexandr Lupandin 没问题。也感谢您的关心。
【解决方案2】:

The google-api-python-client library has a bug where downloads will never be considered done if the Content-length or Content-range header is missing.

由于drive.files.export 不支持分块下载,它不会返回Content-lengthContent-range 标头。

您只需在HttpRequest 上调用execute 即可下载文件,因为drive.files.export 将始终在一个请求中导出整个文件。

如果您仍想使用MediaIoBaseDownload 进行更一般的解决方法,您可以检查MediaDownloadProgress.total_size 是否为None

fh = io.BytesIO()
request = service.files().export_media(fileId=file_id, mimeType=mime_type)
downloader = MediaIoBaseDownload(fh, request)

done = False
while not done:
    status, done = downloader.next_chunk()
    if status.total_size is None:
        # https://github.com/google/google-api-python-client/issues/15
        done = True

【讨论】:

  • 感谢您对问题的如此详细的解释。但是为什么在这种情况下使用MediaIoBaseDownload?我认为最好的解决方案是简单地调用execute(),如上所述。例如,我的代码将是 fh = io.BytesIO().write(service.files().export_media(fileId=file_id, mimeType=mime_type).execute()) 或只是 content = service.files().export_media(fileId=file_id, mimeType=mime_type).execute()
  • @AlexandrLupandin 更新了我的答案并提供了更通用的解决方案。
猜你喜欢
  • 1970-01-01
  • 2015-04-29
  • 1970-01-01
  • 1970-01-01
  • 2017-07-30
  • 1970-01-01
  • 2013-07-25
  • 2017-09-04
  • 1970-01-01
相关资源
最近更新 更多