【问题标题】:How to send image generated by PIL to browser?如何将 PIL 生成的图像发送到浏览器?
【发布时间】:2011-12-14 04:55:46
【问题描述】:

我正在为我的应用程序使用烧瓶。我想将图像(由 PIL 动态生成)发送到客户端而不保存在磁盘上。

知道怎么做吗?

【问题讨论】:

  • Flask 似乎没有对流式二进制数据的可靠支持,而您无法使用 Python 生成器生成这些数据。您可能必须在内存中缓冲图像并发送它。

标签: python streaming python-imaging-library flask temporary-files


【解决方案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)

【讨论】:

  • 意味着你必须能够一次将整个图像保存在内存中,对吧?可能是大图像或其他类型下载的问题。
  • 如何将其插入到我返回的模板中?
  • 我现在如何在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 stackoverflow 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')
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-09-10
        • 1970-01-01
        • 2014-06-18
        • 2015-04-22
        • 1970-01-01
        相关资源
        最近更新 更多