web-dev-qa-db-fra.com

Meilleure façon d'écrire une image dans un Django HttpResponse ()

Je dois servir les images en toute sécurité aux utilisateurs validés uniquement (c'est-à-dire qu'ils ne peuvent pas être servis en tant que fichiers statiques). J'ai actuellement la vue suivante Python dans mon projet Django, mais cela semble inefficace. Des idées pour une meilleure façon?

def secureImage(request,imagePath):
    response = HttpResponse(mimetype="image/png")
    img = Image.open(imagePath)
    img.save(response,'png')
    return response

(L'image est importée de PIL.)

45
k-g-f

Eh bien, le ré-encodage est parfois nécessaire (c'est-à-dire en appliquant un filigrane sur une image tout en gardant l'original intact), mais pour le cas le plus simple, vous pouvez utiliser:

try:
    with open(valid_image, "rb") as f:
        return HttpResponse(f.read(), content_type="image/jpeg")
except IOError:
    red = Image.new('RGBA', (1, 1), (255,0,0,0))
    response = HttpResponse(content_type="image/jpeg")
    red.save(response, "JPEG")
    return response
77
StefanNch

Je suis juste tombé sur un mauvais conseil (pour la production) et j'ai pensé mentionner X-Sendfile qui fonctionne à la fois avec Apache et Nginx et probablement d'autres serveurs Web.

https://pythonhosted.org/xsendfile/

Les serveurs Web modernes comme Nginx sont généralement capables de servir des fichiers plus rapidement, plus efficacement et de manière plus fiable que n'importe quelle application Web qu'ils hébergent. Ces serveurs peuvent également envoyer au client un fichier sur disque comme spécifié par les applications Web qu'ils hébergent. Cette fonctionnalité est communément appelée X-Sendfile.

Cette bibliothèque simple permet à toute application WSGI d'utiliser facilement X-Sendfile, afin qu'elle puisse contrôler si un fichier peut être servi ou quoi faire lorsqu'un fichier est servi, sans écrire d'extensions spécifiques au serveur. Les cas d'utilisation incluent:

  • Limitez les téléchargements de documents aux utilisateurs authentifiés.

  • Enregistrez qui a téléchargé un fichier. Forcer un fichier à télécharger au lieu d'être rendu par le navigateur, ou servez-le avec un nom différent de celui sur le disque, en définissant l'en-tête Content-Disposition.

L'idée de base est d'ouvrir le fichier et de transmettre cette poignée au serveur Web qui renvoie ensuite les octets au client, libérant ainsi votre code python pour gérer la requête suivante. C'est beaucoup plus performant que la solution ci-dessus car un client lent à l'autre extrémité pourrait bloquer votre thread python aussi longtemps que cela prend pour télécharger le fichier.

Voici un dépôt qui montre comment faire cela pour différents serveurs Web et bien qu'il soit assez ancien, il vous donnera au moins une idée de ce que vous devez faire. https://github.com/johnsensible/Django-sendfile

1
boatcoder