How to send image generated by PIL to browser?

前端 未结 5 1976
佛祖请我去吃肉
佛祖请我去吃肉 2020-11-30 22:16

I\'m using flask for my application. I\'d like to send an image (dynamically generated by PIL) to client without saving on disk.

Any idea how to do this ?

相关标签:
5条回答
  • 2020-11-30 22:51

    I was also struggling in the same situation. Finally, I have found its solution using a WSGI application, which is an acceptable object for "make_response" as its argument.

    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)
    

    Please replace "opening image" operations with appropriate PIL operations.

    0 讨论(0)
  • 2020-11-30 22:54

    First, you can save the image to a tempfile and remove the local file (if you have one):

    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)
    

    Second, set the temp file to the response (as per 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
    
    0 讨论(0)
  • 2020-11-30 23:02

    Here's a version without any temp files and the like (see 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')
    

    To use in your code simply do

    @app.route('some/route/')
    def serve_img():
        img = Image.new('RGB', ...)
        return serve_pil_image(img)
    
    0 讨论(0)
  • 2020-11-30 23:04

    It turns out that flask provides a solution (rtm to myself!):

    from flask import abort, send_file
    try:
        return send_file(image_file)
    except:
        abort(404)
    
    0 讨论(0)
  • Mr. Mr. did an excellent job indeed. I had to use BytesIO() instead of 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')
    
    0 讨论(0)
提交回复
热议问题