flask return image created from database

43

16

my images are stored in MongoDB, I'd like to return them to the client, here is how the code is like:

@app.route("/images/<int:pid>.jpg")
def getImage(pid):
    # get image binary from MongoDB, which is bson.Binary type
    return image_binary

However, it seems that I can't return binary directly in Flask?

Here is what I came up with now:

  1. return the base64 of the image binary. -> IE<8 doesn't support this.
  2. create a temp file then return it with send_file.

Is there better solutions ?

wong2

Posted 2012-06-13T14:47:09.303

Reputation: 13 667

1

possible duplicate of How to return images in flask response?

– erickrf – 2014-05-07T04:03:09.237

Answers

79

Create a response object with the data and then set the content type header. Set the content disposition header to attachment if you want the browser to save the file instead of displaying it.

@app.route('/images/<int:pid>.jpg')
def get_image(pid):
    image_binary = read_image(pid)
    response = make_response(image_binary)
    response.headers.set('Content-Type', 'image/jpeg')
    response.headers.set(
        'Content-Disposition', 'attachment', filename='%s.jpg' % pid)
    return response

Relevant: werkzeug.Headers and flask.Response

You can pass a file-like oject to and the header arguments to send_file to let it set up the complete response. Use io.BytesIO for binary data:

return send_file(
    io.BytesIO(image_binary),
    mimetype='image/jpeg',
    as_attachment=True,
    attachment_filename='%s.jpg' % pid)

dav1d

Posted 2012-06-13T14:47:09.303

Reputation: 4 370

1Does send_file close the file object after sending? If it is not a BytesIO, but some other file-object that does require a call to close(), who will call it? – Baruch – 2016-07-26T22:35:44.743

1Using Python 3 and Flask 0.12, providing a binary string (b'&lt;binary image data&gt;') may result in a UnicodeError. send_file() may be just better. – GergelyPolonkai – 2017-01-27T08:47:08.713

35

Just wanted to confirm that dav1d's second suggestion is correct - I tested this (where obj.logo is a mongoengine ImageField), works fine for me:

import io

from flask import current_app as app
from flask import send_file

from myproject import Obj

@app.route('/logo.png')
def logo():
    """Serves the logo image."""

    obj = Obj.objects.get(title='Logo')

    return send_file(io.BytesIO(obj.logo.read()),
                     attachment_filename='logo.png',
                     mimetype='image/png')

Easier than manually creating a Response object and settings its headers.

Jaza

Posted 2012-06-13T14:47:09.303

Reputation: 1 361

This was what I was looking for. – pangeacake – 2015-03-20T00:06:51.283

0

Suppose i have the stored image path with me. The below code helps to send image through.

from flask import send_file
@app.route('/get_image')
def get_image():
    filename = 'uploads\\123.jpg'
    return send_file(filename, mimetype='image/jpg')

uploads is my folder name where my image with 123.jpg is present.

[PS: The uploads folder should be in the current directory as of the your script file]

Hope it helps.

Dikshit Kathuria

Posted 2012-06-13T14:47:09.303

Reputation: 21