benutzerdefinierte HTTP-Header für statische Dateien mit Django
Frage
Ich schreibe eine Bilddatenbank mit Django, und ich möchte eine Schaltfläche hinzufügen, um eine hallo-res Version eines Bildes zu erhalten (die low-res wird in der Detailseite gezeigt). Wenn ich nur einen <a>
Link setzen, wird der Browser das Bild öffnen, anstatt sie herunterzuladen. Hinzufügen eines HTTP-Header wie:
Content-Disposition: attachment; filename="beach008.jpg"
funktioniert, aber da es sich um eine statische Datei ist, will ich nicht die Anforderung mit Django behandeln. Derzeit verwende ich NGINX statische Dateien zu dienen und dynamische Seiten werden über FastCGI auf den Django-Prozess weitergeleitet. Ich denke über NGINX add-header
Kommando, konnte aber die filename="xx"
Teil eingestellt ?. Oder vielleicht gibt es eine Möglichkeit, die Anfrage in Django zu handhaben, sondern machen NGINX dienen den Inhalt?
Lösung
Wenn Ihr django app von nginx proxied wird können Sie x-Accell-redirect . Sie benötigen einen speziellen Header in Ihrer Antwort passieren, nginx wird intercepet diese und starten Sie die Datei dienen, können Sie auch Content-Disposition in der gleichen Antwort übergeben Sie einen Download zu erzwingen.
Diese Lösung ist gut, wenn Sie welche Benutzer Acess diese Dateien steuern möchten.
Sie können auch eine Konfiguration wie folgt verwenden:
#files which need to be forced downloads
location /static/high_res/ {
root /project_root;
#don't ever send $request_filename in your response, it will expose your dir struct, use a quick regex hack to find just the filename
if ($request_filename ~* ^.*?/([^/]*?)$) {
set $filename $1;
}
#match images
if ($filename ~* ^.*?\.((jpg)|(png)|(gif))$) {
add_header Content-Disposition "attachment; filename=$filename";
}
}
location /static {
root /project_root;
}
Dies wird herunterladen zwingen auf alle Bilder in einigen loestes Ordner (mediaroot / high_rest). Und für die anderen statischen Dateien wird es wie normale verhalten. Bitte beachten Sie, dass dies ein modifizierte schneller Hack, der für mich arbeitet. Es kann Auswirkungen auf die Sicherheit haben, so verwenden Sie es mit Vorsicht.
Andere Tipps
Ich schrieb ein einfaches Dekorateur, für django.views.static.serve Ansicht
, die perfekt funktioniert für mich.
def serve_download(view_func):
def _wrapped_view_func(request, *args, **kwargs):
response = view_func(request, *args, **kwargs)
response['Content-Type'] = 'application/octet-stream';
import os.path
response['Content-Disposition'] = 'attachment; filename="%s"' % os.path.basename(kwargs['path'])
return response
return _wrapped_view_func
Sie können auch mit nginx Mime-Typ spielen
http://wiki.codemongers.com/NginxHttpCoreModule#types
Diese Lösung nicht für mich arbeiten, weil ich sowohl direkten Link für die Datei haben wollte (so können Benutzer Bilder sehen, zum Beispiel), und Download-Link.
Was ich tue ist jetzt eine andere URL zum Download zu verwenden, als für ‚Ansichten‘, und fügen Sie den Dateinamen als URL arg:
übliche Medien Link: http://xx.com/media/images/lores/f_123123.jpg
Download-Link: http://xx.com/downs/hires/f_12323?beach008.jpg
und nginx hat eine Config wie folgt aus:
location /downs/ {
root /var/www/nginx-attachment;
add_header Content-Disposition 'attachment; filename="$args"';
}
, aber Ich mag es wirklich nicht den Geruch von ihm.