PIL 无法识别流入 io.BytesIO 的 Google 驱动器图像的图像文件

PIL cannot identify image file for a Google Drive image streamd into io.BytesIO

我正在使用驱动器 API 在 Python 中下载一个 image. Following their file downloading documentation,我最终得到一个变量 fh,它是一个已填充的 io.BytesIO实例。我尝试将其保存为图像:

file_id = "0BwyLGoHzn5uIOHVycFZpSEwycnViUjFYQXR5Nnp6QjBrLXJR"
request = 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 {} {}%.'.format(file['name'],
                                    int(status.progress() * 100)))
    fh.seek(0)
image = Image.open(fh) # error

错误是:cannot identify image file <_io.BytesIO object at 0x106cba890>。实际上,another image 不会出现错误,但大多数图像都会抛出该错误,包括我在此 post.

开头链接的那个

阅读 this answer 后,我将最后一行更改为:

byteImg = fh.read()
dataBytesIO = io.BytesIO(byteImg)
image = Image.open(dataBytesIO) # still the same error

我也试过 this answer,我将第一个代码块的最后一行更改为

byteImg = fh.read()
image = Image.open(StringIO(byteImg))

但我仍然收到 cannot identify image file <StringIO.StringIO instance at 0x106471e60> 错误。

我试过使用替代品(请求、urllib)但没有结果。如果我手动下载图片,我可以 Image.open 图片。

这个错误在一个月前没有出现,最近突然出现在这个代码所在的应用程序中。我花了几天时间调试这个错误但没有成功,最后把这个问题提交给 Stack Overflow。我正在使用 from PIL import Image.

放弃云端硬盘服务 MediaIOBaseDownload。相反,使用媒体文件的 webContentLink 属性(link 用于在浏览器中下载文件的内容,仅适用于具有二进制内容的文件)。阅读更多 here.

有了这些内容 link,我们可以使用另一种流式传输形式——requestsshutil 库以及 — 来获取图像。

import requests
import shutil

r = requests.get(file['webContentLink'], stream=True)
with open('output_file', 'wb') as f:
    shutil.copyfileobj(r.raw, f)