Ich möchte, dass Benutzer auf der Website Dateien herunterladen können, deren Pfade verdeckt sind, damit sie nicht direkt heruntergeladen werden können.
Zum Beispiel möchte ich, dass die URL ungefähr so lautet: http://example.com/download/?f=somefile.txt
Und auf dem Server weiß ich, dass sich alle herunterladbaren Dateien im Ordner befinden /home/user/files/
.
Gibt es eine Möglichkeit, Django dazu zu bringen, diese Datei zum Herunterladen bereitzustellen, anstatt zu versuchen, eine URL und eine Ansicht zu finden, um sie anzuzeigen?
Antworten:
Für das "Beste aus zwei Welten" können Sie die Lösung von S.Lott mit dem xsendfile-Modul kombinieren : django generiert den Pfad zur Datei (oder zur Datei selbst), aber die eigentliche Dateiservierung wird von Apache / Lighttpd übernommen. Sobald Sie mod_xsendfile eingerichtet haben, dauert die Integration in Ihre Ansicht einige Codezeilen:
Dies funktioniert natürlich nur, wenn Sie die Kontrolle über Ihren Server haben oder Ihr Hosting-Unternehmen mod_xsendfile bereits eingerichtet hat.
BEARBEITEN:
EDIT: Für
nginx
überprüfen diese , verwendet esX-Accel-Redirect
anstelle vonapache
X-Sendfile - Header.quelle
smart_str
funktioniert das nicht wie vorgesehen, da das Apache-Modul X-Sendfile die mit smart_str codierte Zeichenfolge nicht dekodieren kann. So kann beispielsweise die Datei "Örinää.mp3" nicht bedient werden. Und wenn man den smart_str weglässt, löst der Django selbst einen ASCII-Codierungsfehler aus, da alle Header vor dem Senden im ASCII-Format codiert werden. Die einzige Möglichkeit, dieses Problem zu umgehen, besteht darin, die Dateinamen von X-sendfile auf diejenigen zu reduzieren, die nur aus ASCII bestehen.Ein "Download" ist einfach eine Änderung des HTTP-Headers.
Informationen zum Antworten mit einem Download finden Sie unter http://docs.djangoproject.com/de/dev/ref/request-response/#telling-the-browser-to-treat-the-response-as-a-file-attachment .
Sie benötigen nur eine URL-Definition für
"/download"
.Die Anfrage
GET
oder dasPOST
Wörterbuch enthält die"f=somefile.txt"
Informationen.Ihre Ansichtsfunktion führt einfach den Basispfad mit dem
f
Wert " " zusammen, öffnet die Datei, erstellt ein Antwortobjekt und gibt es zurück. Es sollten weniger als 12 Codezeilen sein.quelle
filepath = filepath.replace('..', '').replace('/', '')
Für eine sehr einfache, aber nicht effiziente oder skalierbare Lösung können Sie einfach die integrierte Django-
serve
Ansicht verwenden. Dies ist hervorragend für schnelle Prototypen oder einmalige Arbeiten geeignet. Wie in dieser Frage bereits erwähnt, sollten Sie in der Produktion so etwas wie Apache oder Nginx verwenden.quelle
S.Lott hat die "gute" / einfache Lösung und elo80ka hat die "beste" / effiziente Lösung. Hier ist eine "bessere" / mittlere Lösung - kein Server-Setup, aber effizienter für große Dateien als das naive Update:
http://djangosnippets.org/snippets/365/
Grundsätzlich übernimmt Django weiterhin das Bereitstellen der Datei, lädt jedoch nicht das Ganze auf einmal in den Speicher. Auf diese Weise kann Ihr Server (langsam) eine große Datei bereitstellen, ohne die Speichernutzung zu erhöhen.
Auch hier ist das X-SendFile von S.Lott für größere Dateien immer noch besser. Aber wenn Sie sich damit nicht beschäftigen können oder wollen, werden Sie mit dieser mittleren Lösung ohne Probleme eine bessere Effizienz erzielen.
quelle
django.core.servers.httpbase
undokumentierten privaten Modul, das oben im Code " NICHT FÜR PRODUKTIONSVERWENDUNG VERWENDEN !!! " ein großes Warnzeichen hat, das seit seiner Erstellung in der Datei enthalten ist . In jedem Fall wurde dieFileWrapper
Funktionalität , auf die sich dieses Snippet stützt, in Django 1.9 entfernt.Versuchte @ Rocketmonkeys-Lösung, aber heruntergeladene Dateien wurden als * .bin gespeichert und mit zufälligen Namen versehen. Das ist natürlich nicht gut. Das Hinzufügen einer weiteren Zeile von @ elo80ka löste das Problem.
Hier ist der Code, den ich jetzt verwende:
Sie können jetzt Dateien in einem privaten Verzeichnis (weder in / media noch / public_html) speichern und sie über Django bestimmten Benutzern oder unter bestimmten Umständen zugänglich machen.
Ich hoffe es hilft.
Dank @ elo80ka, @ S.Lott und @Rocketmonkeys für die Antworten haben wir die perfekte Lösung gefunden, die alle kombiniert =)
quelle
filename="%s"
im Header "Content-Disposition" doppelte Anführungszeichen um den Dateinamen ein , um Probleme mit Leerzeichen in Dateinamen zu vermeiden. Referenzen: Dateinamen mit Leerzeichen werden beim Download abgeschnitten . WieFileWrapper(open(path.abspath(file_name), 'rb'))
FileWrapper
wurde entfernt seit Django 1.9from wsgiref.util import FileWrapper
Erwähnen Sie nur das in Django 1.10 verfügbare FileResponse- Objekt
Bearbeiten: Ich bin gerade auf meine eigene Antwort gestoßen, als ich nach einer einfachen Möglichkeit gesucht habe, Dateien über Django zu streamen. Hier ist ein vollständigeres Beispiel (für mich in Zukunft). Es wird davon ausgegangen, dass der FileField-Name lautet
imported_file
views.py
urls.py
quelle
Es wurde oben erwähnt, dass die mod_xsendfile-Methode keine Nicht-ASCII-Zeichen in Dateinamen zulässt.
Aus diesem Grund steht für mod_xsendfile ein Patch zur Verfügung, mit dem jede Datei gesendet werden kann, sofern der Name url-codiert ist, und der zusätzliche Header:
Wird auch gesendet.
http://ben.timby.com/?p=149
quelle
Versuchen Sie: https://pypi.python.org/pypi/django-sendfile/
"Abstraktion zum Auslagern von Datei-Uploads auf den Webserver (z. B. Apache mit mod_xsendfile), sobald Django die Berechtigungen usw. überprüft hat."
quelle
Sie sollten sendfile apis verwenden, die von gängigen Servern wie
apache
odernginx
in der Produktion bereitgestellt werden . Viele Jahre lang habe ich die sendfile-API dieser Server zum Schutz von Dateien verwendet. Anschließend wurde eine einfache Middleware-basierte Django-App für diesen Zweck erstellt, die sowohl für Entwicklungs- als auch für Produktionszwecke geeignet ist . Hier können Sie auf den Quellcode zugreifen .UPDATE: In der neuen Version verwendet der
python
Anbieter DjangoFileResponse
falls verfügbar, und Unterstützung für viele Serverimplementierungen von lighthttp, caddy bis hiawathaVerwendung
fileprovider
App hinzufügen zuINSTALLED_APPS
Einstellungen ,fileprovider.middleware.FileProviderMiddleware
zuMIDDLEWARE_CLASSES
EinstellungenFILEPROVIDER_NAME
Einstellungen aufnginx
oderapache
in der Produktion einstellen , standardmäßigpython
für Entwicklungszwecke.Setzen Sie in Ihren Klassen- oder Funktionsansichten den Antwortheaderwert
X-File
auf den absoluten Pfad zur Datei. Beispielsweise,django-fileprovider
so implementiert, dass Ihr Code nur minimal geändert werden muss.Nginx-Konfiguration
Um die Datei vor direktem Zugriff zu schützen, können Sie die Konfiguration als festlegen
Hier wird
nginx
eine Standort-URL festgelegt, auf die/files/
nur intern zugegriffen werden kann. Wenn Sie die obige Konfiguration verwenden, können Sie X-File wie folgt festlegen:Wenn Sie dies mit der Nginx-Konfiguration tun, wird die Datei geschützt und Sie können die Datei auch von Django aus steuern
views
quelle
Django empfiehlt, dass Sie einen anderen Server verwenden, um statische Medien bereitzustellen (ein anderer Server, der auf demselben Computer ausgeführt wird, ist in Ordnung). Sie empfehlen die Verwendung von Servern wie lighttp .
Dies ist sehr einfach einzurichten. Jedoch. Wenn 'somefile.txt' auf Anfrage generiert wird (der Inhalt ist dynamisch), möchten Sie möglicherweise, dass Django ihn bereitstellt.
Django Docs - Statische Dateien
quelle
quelle
Ein weiteres Projekt, das Sie sich ansehen sollten: http://readthedocs.org/docs/django-private-files/en/latest/usage.html Sieht vielversprechend aus, hat es aber noch nicht selbst getestet.
Grundsätzlich abstrahiert das Projekt die mod_xsendfile-Konfiguration und ermöglicht Ihnen folgende Aktionen:
quelle
django-private-files
...Ich habe das gleiche Problem mehr als einmal gesehen und so mit dem xsendfile-Modul und den Auth-View-Dekorateuren die Django-Dateibibliothek implementiert . Sie können es gerne als Inspiration für Ihre eigene Lösung verwenden.
https://github.com/danielsokolowski/django-filelibrary
quelle
Bereitstellung eines geschützten Zugriffs auf den statischen HTML-Ordner über https://github.com/johnsensible/django-sendfile : https://gist.github.com/iutinvg/9907731
quelle
Ich habe ein Projekt dazu gemacht. Sie können sich mein Github-Repo ansehen:
https://github.com/nishant-boro/django-rest-framework-download-expert
Dieses Modul bietet eine einfache Möglichkeit, Dateien zum Herunterladen im Django Rest Framework mithilfe des Apache-Moduls Xsendfile bereitzustellen. Es bietet außerdem die zusätzliche Funktion, Downloads nur für Benutzer einer bestimmten Gruppe bereitzustellen
quelle