问题描述
我正在使用 Python Flask 框架 来构建网站.由于我将上传的图像存储在 MongoDB 中,因此我构建了一个简单的端点来按 id 提供图像:
I'm using the Python Flask framework to build a website. Since I'm storing uploaded images in MongoDB, I built a simple endpoint to serve the images by 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
并在需要时为他们服务.所以我从这个开始:
This works perfectly well. But because the images are often very large I now want to be able to also serve up thumbnails of the original images. So using Pillow I want to resize the images, store/cache them in /tmp
and serve them up when needed. So I started off with this:
@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)
当我现在注释掉问题所在的行并打开首页(加载几张图片)时,所有图片都加载正常,我看到了这一点(如预期):
When I now comment out the line with the problem and open the front page (which loads a couple of images) all images load fine and I see this (as expected):
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
但是当我运行上面粘贴的代码时(没有注释问题行),图像没有加载,我在终端中看到了这一点:
but when I run the code as I pasted it above (with the problem line not commented) the images don't load, and I see this in the terminal:
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
除了这些东西,我在终端中看不到任何错误.当我尝试在浏览器中加载直接 url 时,它说 由于包含错误,图像无法显示.
.我现在想知道两件事:
Except for these things I see no error whatsoever in the terminal. When I try to load a direct url in the browser it says The image cannot be displayed because it contains errors.
. I now wonder about two things:
- 即使所有请求似乎都成功 (200),我也没有在浏览器中看到图像.为什么?
- 即使将图像加载到 Pillow 需要一段时间(我认为不会),我仍然希望图像最终加载.
有谁知道为什么当我将图像加载到 Pillow 时没有提供图像?欢迎所有提示!
Does anybody know why the images are not served when I load them into Pillow? All tips are welcome!
推荐答案
Pillow 没有任何问题.您的问题是您正在提供空响应.如果您正在提供缩略图,您要求 Pillow 阅读文件:
You don't have any problems with Pillow. Your problem is that you are serving an empty response. If you are serving a thumbnail, you ask Pillow to read the file:
if desiredWidthStr or desiredHeightStr:
print 'THUMBNAIL'
im = Image.open(userDoc.file_) # reads from the file object
然后您尝试从那个相同的文件对象提供服务:
You then try and serve from that same 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()
已经移动了文件指针.这取决于图像类型实际读取了多少以及图像指针到那时所在的位置.
The userDoc.file_.read()
here will return, at best, a partial image since Image.open()
has already moved the file pointer. It depends on the image type how much is actually read and where the image pointer is located at by that time.
添加 file.seek()
调用,您将看到您的图像重新出现:
Add in a file.seek()
call and you'll see your image re-appear:
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)
这篇关于为什么在 PIL(low) 中读取图像会破坏 Flask 图像端点?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!