为什么在PIL中读取图像(低)会破坏Flask图像的终点?

时间:2015-03-19 15:49:05

标签: python image flask python-imaging-library pillow

我使用Python Flask framework构建网站。由于我在MongoDB中存储上传的图像,我构建了一个简单的端点来通过id提供图像:

@app.route('/doc/<docId>')
def getDoc(docId):
    userDoc = UserDocument.objects(id=docId).first()
    if not userDoc:
        return abort(404)

    return Response(userDoc.file_.read(), mimetype=userDoc.file_.content_type)

这非常有效。但由于图像通常非常大,我现在希望能够提供原始图像的缩略图。因此,使用Pillow我希望调整图像大小,将它们存储/缓存在/tmp中,并在需要时提供它们。所以我从这开始:

@app.route('/doc/<docId>')
def getDoc(docId):
    userDoc = UserDocument.objects(id=docId).first()
    if not userDoc:
        return abort(404)

    desiredWidthStr = request.args.get('width')
    desiredHeightStr = request.args.get('height')
    if desiredWidthStr or desiredHeightStr:    
        print 'THUMBNAIL'
        # Load the image in Pillow
        im = Image.open(userDoc.file_)  # <=== THE PROBLEM!!!
        # TODO: resize and save the image in /tmp

    print 'NORMAL'
    return Response(userDoc.file_.read(), mimetype=userDoc.file_.content_type)

当我现在注释掉有问题的行并打开首页(加载几张图片)时,所有图片都加载正常,我看到了(正如预期的那样):

THUMBNAIL
NORMAL
THUMBNAIL
NORMAL
THUMBNAIL
NORMAL
212.xx.xx.xx - - [2015-03-19 16:57:02] "GET /doc/54e74956724b5907786e9918?width=100 HTTP/1.1" 200 139588 0.744827
212.xx.xx.xx - - [2015-03-19 16:57:03] "GET /doc/54e7495c724b5907786e991b?width=100 HTTP/1.1" 200 189494 1.179268
212.xx.xx.xx - - [2015-03-19 16:57:03] "GET /doc/5500c5d1724b595cf71b4d49?width=100 HTTP/1.1" 200 264593 1.416928

但是当我在上面粘贴代码时运行代码(问题行未注释)图像不会加载,我在终端中看到了这一点:

THUMBNAIL
THUMBNAIL
THUMBNAIL
NORMAL
NORMAL
NORMAL
212.xx.xx.xx - - [2015-03-19 16:58:11] "GET /doc/54e74956724b5907786e9918?width=100 HTTP/1.1" 200 138965 0.657734
212.xx.xx.xx - - [2015-03-19 16:58:11] "GET /doc/54e7495c724b5907786e991b?width=100 HTTP/1.1" 200 188871 0.753112
212.xx.xx.xx - - [2015-03-19 16:58:11] "GET /doc/5500c5d1724b595cf71b4d49?width=100 HTTP/1.1" 200 257495 1.024860

除了这些东西,我发现终端没有任何错误。当我尝试在浏览器中加载直接网址时,会显示The image cannot be displayed because it contains errors.。我现在想知道两件事:

  1. 即使所有请求似乎都成功(200),我也不会在浏览器中看到图像。为什么?
  2. 即使将图像加载到Pillow中需要一段时间(我认为它没有),我仍然希望图像能够加载到最后。
  3. 当我将图像加载到枕头中时,有人知道为什么没有提供图像吗?欢迎所有提示!

1 个答案:

答案 0 :(得分:8)

Pillow没有任何问题。您的问题是您正在提供空响应。如果您正在提供缩略图,请让Pillow 读取文件

if desiredWidthStr or desiredHeightStr:    
    print 'THUMBNAIL'
    im = Image.open(userDoc.file_)  # reads from the file object

然后尝试从相同的文件对象中提供服务:

if desiredWidthStr or desiredHeightStr:    
    print 'THUMBNAIL'
    # Load the image in Pillow
    im = Image.open(userDoc.file_)  # <=== THE PROBLEM!!!
    # TODO: resize and save the image in /tmp

return Response(userDoc.file_.read(), mimetype=userDoc.file_.content_type)

此处的userDoc.file_.read()最多会返回部分图像,因为Image.open()已经移动了文件指针。这取决于图像类型实际读取了多少以及图像指针到那时的位置。

添加 file.seek()来电,您会看到您的图片重新显示:

if desiredWidthStr or desiredHeightStr:    
    print 'THUMBNAIL'
    # Load the image in Pillow
    im = Image.open(userDoc.file_)

print 'NORMAL'
userDoc.file_.seek(0)  # ensure we are reading from the start
return Response(userDoc.file_.read(), mimetype=userDoc.file_.content_type)