web-dev-qa-db-fra.com

Flask pour retourner l'image stockée dans la base de données

Mes images sont stockées dans un MongoDB, et je voudrais les retourner au client, voici à quoi ressemble le code:

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

Cependant, il semble que je ne puisse pas retourner le binaire directement dans Flask? Mon idée jusqu'ici:

  1. Retourner le base64 du binaire de l'image. Le problème est que IE <8 ne prend pas en charge cela.
  2. Créez un fichier temporaire puis renvoyez-le avec send_file.

Y a-t-il de meilleures solutions?

58
wong2

Créez un objet de réponse avec les données, puis définissez l'en-tête de type de contenu. Définissez l'en-tête de disposition de contenu sur attachment si vous souhaitez que le navigateur enregistre le fichier au lieu de l'afficher.

@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

Pertinent: werkzeug.Headers et flask.Response

Vous pouvez passer un objet de type fichier à et les arguments d'en-tête à send_file pour le laisser configurer la réponse complète. Utilisation io.BytesIO pour les données binaires:

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

Je voulais juste confirmer que la deuxième suggestion de dav1d est correcte - j'ai testé cela (où obj.logo est un ImageField mongoengine), fonctionne très bien pour moi:

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')

Plus simple que de créer manuellement un objet Response et de définir ses en-têtes.

39
Jaza

Supposons que j'ai le chemin d'image stocké avec moi. Le code ci-dessous permet d'envoyer l'image à travers.

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

uploads est le nom de mon dossier où mon image avec 123.jpg est présente.

[PS: le dossier de téléchargement doit être dans le répertoire en cours à partir du fichier de script]

J'espère que ça aide.

5
Dikshit Kathuria