サイトのユーザーが、直接ダウンロードできないようにパスが隠されているファイルをダウンロードできるようにしたい。
たとえば、URL を次のようにしたいと考えています。http://example.com/download/?f=somefile.txt
サーバー上では、ダウンロード可能なすべてのファイルがフォルダーにあることがわかっています/home/user/files/
。
URLを見つけて表示するのではなく、Djangoにそのファイルをダウンロード用に提供させる方法はありますか?
サイトのユーザーが、直接ダウンロードできないようにパスが隠されているファイルをダウンロードできるようにしたい。
たとえば、URL を次のようにしたいと考えています。http://example.com/download/?f=somefile.txt
サーバー上では、ダウンロード可能なすべてのファイルがフォルダーにあることがわかっています/home/user/files/
。
URLを見つけて表示するのではなく、Djangoにそのファイルをダウンロード用に提供させる方法はありますか?
「両方の長所」を得るには、S.Lott のソリューションをxsendfile モジュールと組み合わせることができます。djangoはファイル (またはファイル自体) へのパスを生成しますが、実際のファイル サービングは Apache/Lighttpd によって処理されます。mod_xsendfile を設定したら、数行のコードでビューと統合できます。
from django.utils.encoding import smart_str
response = HttpResponse(mimetype='application/force-download') # mimetype is replaced by content_type for django 1.7
response['Content-Disposition'] = 'attachment; filename=%s' % smart_str(file_name)
response['X-Sendfile'] = smart_str(path_to_file)
# It's usually a good idea to set the 'Content-Length' header too.
# You can also set any other required headers: Cache-Control, etc.
return response
もちろん、これはサーバーを制御できる場合、またはホスティング会社が mod_xsendfile を既にセットアップしている場合にのみ機能します。
編集:
mimetype は、django 1.7 の content_type に置き換えられました
response = HttpResponse(content_type='application/force-download')
編集:これnginx
を確認するには、X-
Sendfileヘッダーの代わりに使用します。X-Accel-Redirect
apache
「ダウンロード」は、単に HTTP ヘッダーの変更です。
ダウンロードで応答する方法については、http://docs.djangoproject.com/en/dev/ref/request-response/#telling-the-browser-to-treat-the-response-as-a-file-attachmentを参照してください。 .
に必要な URL 定義は 1 つだけです"/download"
。
リクエストGET
またはPOST
ディクショナリに"f=somefile.txt"
情報が含まれます。
ビュー関数は単純にベース パスを " f
" 値とマージし、ファイルを開き、応答オブジェクトを作成して返します。コードは 12 行未満にする必要があります。
S.Lottには「優れた」/シンプルなソリューションがあり、elo80kaには「最良の」/効率的なソリューションがあります。これが「より良い」/中間の解決策です。サーバーのセットアップはありませんが、大きなファイルの場合は、単純な修正よりも効率的です。
http://djangosnippets.org/snippets/365/
基本的に、Djangoは引き続きファイルの提供を処理しますが、すべてを一度にメモリにロードするわけではありません。これにより、サーバーはメモリ使用量を増やすことなく、大きなファイルを(ゆっくりと)提供できます。
繰り返しになりますが、S.LottのX-SendFileは、より大きなファイルに適しています。しかし、それを気にすることができない、またはしたくない場合は、この中間のソリューションを使用すると、面倒なことなく効率を向上させることができます。
mod_xsendfile メソッドでは、ファイル名に非 ASCII 文字を使用できないことは前述しました。
このため、名前が URL エンコードされていて、追加のヘッダーがある限り、任意のファイルを送信できるようにする mod_xsendfile 用のパッチを用意しています。
X-SendFile-Encoding: url
も送られます。
試してください:https ://pypi.python.org/pypi/django-sendfile/
「Djangoが権限などをチェックした後、ファイルのアップロードをWebサーバー(たとえば、mod_xsendfileを使用したApache)にオフロードするための抽象化。」
apache
またはnginx
本番環境などの一般的なサーバーによって提供される sendfile API を使用する必要があります。何年もの間、ファイルを保護するためにこれらのサーバーの sendfile API を使用していました。次に、この目的のために、開発と運用の両方の目的に適したシンプルなミドルウェア ベースの django アプリを作成しました。ソース コードはこちらからアクセスできます。
更新: 新しいバージョンのpython
プロバイダーではFileResponse
、利用可能な場合は django を使用し、lighthttp、caddy から hiawatha までの多くのサーバー実装のサポートも追加します
使用法
pip install django-fileprovider
fileprovider
アプリをINSTALLED_APPS
設定に追加し、fileprovider.middleware.FileProviderMiddleware
に追加MIDDLEWARE_CLASSES
FILEPROVIDER_NAME
を本番環境に設定しnginx
ます。apache
デフォルトではpython
開発目的です。クラスベース ビューまたは関数ビューで、応答ヘッダーX-File
の値をファイルへの絶対パスに設定します。例えば、
def hello(request):
// code to check or protect the file from unauthorized access
response = HttpResponse()
response['X-File'] = '/absolute/path/to/file'
return response
django-fileprovider
コードの変更が最小限で済むように実装されています。
Nginx の構成
ファイルを直接アクセスから保護するには、構成を次のように設定できます。
location /files/ {
internal;
root /home/sideffect0/secret_files/;
}
ここでは、内部アクセスのみnginx
のロケーション URL/files/
を設定します。上記の構成を使用している場合は、X-File を次のように設定できます。
response['X-File'] = '/files/filename.extension'
nginx の設定でこれを行うことで、ファイルは保護され、django からファイルを制御することもできますviews
Django は、別のサーバーを使用して静的メディアを提供することをお勧めします (同じマシンで別のサーバーを実行しても問題ありません)。彼らは、 lighttpなどのサーバーの使用を推奨しています。
これは非常に簡単に設定できます。でも。「somefile.txt」が要求に応じて生成される場合 (コンテンツは動的です)、django に提供させたい場合があります。
私は同じ問題に何度も直面したため、 xsendfile モジュールと認証ビューデコレータdjango-filelibraryを使用して実装しました。独自のソリューションのインスピレーションとして自由に使用してください。
見てみる別のプロジェクト: http://readthedocs.org/docs/django-private-files/en/latest/usage.html 有望に見えますが、まだ自分でテストしていません。
基本的に、プロジェクトは mod_xsendfile 構成を抽象化し、次のようなことができるようにします。
from django.db import models
from django.contrib.auth.models import User
from private_files import PrivateFileField
def is_owner(request, instance):
return (not request.user.is_anonymous()) and request.user.is_authenticated and
instance.owner.pk = request.user.pk
class FileSubmission(models.Model):
description = models.CharField("description", max_length = 200)
owner = models.ForeignKey(User)
uploaded_file = PrivateFileField("file", upload_to = 'uploads', condition = is_owner)
https://github.com/johnsensible/django-sendfileを使用して静的 html フォルダーへの保護されたアクセスを提供する: https://gist.github.com/iutinvg/9907731