如何将 PIL 生成的图像发送到浏览器?
Posted
技术标签:
【中文标题】如何将 PIL 生成的图像发送到浏览器?【英文标题】:How to send image generated by PIL to browser? 【发布时间】:2011-12-14 04:55:46 【问题描述】:我正在为我的应用程序使用烧瓶。我想将图像(由 PIL 动态生成)发送到客户端而不保存在磁盘上。
知道怎么做吗?
【问题讨论】:
Flask 似乎没有对流式二进制数据的可靠支持,而您无法使用 Python 生成器生成这些数据。您可能必须在内存中缓冲图像并发送它。 【参考方案1】:这是一个没有任何临时文件等的版本(请参阅here):
def serve_pil_image(pil_img):
img_io = StringIO()
pil_img.save(img_io, 'JPEG', quality=70)
img_io.seek(0)
return send_file(img_io, mimetype='image/jpeg')
要在您的代码中使用,只需这样做
@app.route('some/route/')
def serve_img():
img = Image.new('RGB', ...)
return serve_pil_image(img)
【讨论】:
意味着你必须能够一次将整个图像保存在内存中,对吧?可能是大图像或其他类型下载的问题。 如何将其插入到我返回的模板中? Python3 需要使用 ByteIO:fadeit.dk/blog/post/python3-flask-pil-in-memory-image 我现在如何在img
标签的src
属性中引用文件
对于那些询问如何在img
标记的src
属性中引用文件的人,只需使用将提供图像@app.route('/docs/<filename>')
的端点,然后在html 中使用`src= "/docs/some_img.jpg"【参考方案2】:
先生。先生确实做得很好。我不得不使用 BytesIO() 而不是 StringIO()。
def serve_pil_image(pil_img):
img_io = BytesIO()
pil_img.save(img_io, 'JPEG', quality=70)
img_io.seek(0)
return send_file(img_io, mimetype='image/jpeg')
【讨论】:
我遇到了一个问题,即 BytesIO 不是字符串,send_file
需要一个字符串作为路径。如何从 BytesIO 对象中获取路径?
我认为字节作为 8 位对象出现,可以解释为字符串。无论如何 - 我不确定为什么它不适合你,试试 StringIO() 吧?
它实际上工作正常,我只是没有在我的 html 中正确引用它。现在使用url_for()
,它工作正常。
我有这样的设置,但是当我在 docker 中运行我的应用程序时,我得到RuntimeError: Attempted implicit sequence conversion but the response object is in direct passthrough mode.
任何想法在哪里设置它?【参考方案3】:
首先,您可以将图像保存到tempfile 并删除本地文件(如果有的话):
from tempfile import NamedTemporaryFile
from shutil import copyfileobj
from os import remove
tempFileObj = NamedTemporaryFile(mode='w+b',suffix='jpg')
pilImage = open('/tmp/myfile.jpg','rb')
copyfileobj(pilImage,tempFileObj)
pilImage.close()
remove('/tmp/myfile.jpg')
tempFileObj.seek(0,0)
其次,将临时文件设置为响应(根据this *** question):
from flask import send_file
@app.route('/path')
def view_method():
response = send_file(tempFileObj, as_attachment=True, attachment_filename='myfile.jpg')
return response
【讨论】:
不再工作:TypeError: 'file' object is not callable
这里动态创建的文件是什么?
@user1953366 - 在这个例子中,正在创建的文件是 myfile.jpg,但我会认真检查下面的 mr-mr 的答案,因为它不需要创建临时文件更有效.
临时文件也写入磁盘?这是如何被接受的响应?【参考方案4】:
原来flask提供了一个解决方案(rtm给我自己!):
from flask import abort, send_file
try:
return send_file(image_file)
except:
abort(404)
【讨论】:
【参考方案5】:我也在同样的情况下苦苦挣扎。最后,我找到了使用 WSGI 应用程序的解决方案,它是“make_response”作为其参数的可接受对象。
from Flask import make_response
@app.route('/some/url/to/photo')
def local_photo():
print('executing local_photo...')
with open('test.jpg', 'rb') as image_file:
def wsgi_app(environ, start_response):
start_response('200 OK', [('Content-type', 'image/jpeg')])
return image_file.read()
return make_response(wsgi_app)
请将“打开图像”操作替换为适当的 PIL 操作。
【讨论】:
【参考方案6】: return send_file(fileName, mimetype='image/png')
【讨论】:
以上是关于如何将 PIL 生成的图像发送到浏览器?的主要内容,如果未能解决你的问题,请参考以下文章
如何在 Python 中使用 PIL 将图像合成到另一个图像上?