web-dev-qa-db-ja.com

Django HttpResponse()に画像を書き込む最良の方法

検証済みのユーザーのみに画像を安全に提供する必要があります(つまり、静的ファイルとして提供することはできません)。現在、私は次のPythonビューを私のDjangoプロジェクトに表示していますが、非効率的なようです。より良い方法のアイデアはありますか?

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

(画像はPILからインポートされます。)

45
k-g-f

まあ、再エンコードが必要な場合があります(つまり、オリジナルに手を加えずに画像に透かしを適用するなど)。

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

(プロダクション用の)やや悪いアドバイスに出くわしただけで、ApacheとNginxの両方で動作するX-Sendfileと、おそらく他のWebサーバーでも動作すると思います。

https://pythonhosted.org/xsendfile/

Nginxのような最新のWebサーバーは、一般に、ホストするWebアプリケーションよりも高速、効率的、信頼性の高いファイルを提供できます。これらのサーバーは、ホストするWebアプリケーションによって指定されたディスク上のファイルをクライアントに送信することもできます。この機能は一般にX-Sendfileとして知られています。

この単純なライブラリーにより、任意のWSGIアプリケーションがX-Sendfileを簡単に使用できるようになるため、サーバー固有の拡張機能を記述せずに、ファイルを提供できるかどうか、またはファイルが提供されたときに何をするかを制御できます。使用例は次のとおりです。

  • ドキュメントのダウンロードを認証されたユーザーに制限します。

  • ファイルをダウンロードしたユーザーを記録します。 Content-Dispositionヘッダーを設定して、ブラウザーでレンダリングする代わりにファイルを強制的にダウンロードするか、ディスク上のファイルとは異なる名前でファイルを提供します。

基本的な考え方は、ファイルを開いてそのハンドルをウェブサーバーに渡し、クライアントにバイトを返し、pythonコードを解放して次のリクエストを処理することです。これは、上記の解決策は、反対側の遅いクライアントがファイルのダウンロードにかかる限り、pythonスレッドをハングアップさせる可能性があるためです。

これは、さまざまなWebサーバーでこれを行う方法を示すレポジトリであり、かなり古いものですが、少なくとも、何をする必要があるかがわかるでしょう。 https://github.com/johnsensible/Django-sendfile

1
boatcoder