2008-11-04 9 views
9

Ich schreibe eine Bilddatenbank mit Django, und ich möchte einen Button hinzufügen, um eine hi-res-Version eines Bildes (die Low-Res wird auf der Detailseite angezeigt) . Wenn ich nur einen <a> Link einstelle, öffnet der Browser das Bild, anstatt es herunterzuladen. Hinzufügen eines HTTP-Header wie:benutzerdefinierte HTTP-Header für statische Dateien mit Django

Content-Disposition: attachment; filename="beach008.jpg" 

funktioniert, aber da es sich um eine statische Datei ist, möchte ich nicht die Anforderung mit Django behandeln. Zurzeit verwende ich NGINX, um statische Dateien zu liefern, und dynamische Seiten werden über FastCGI zum Django-Prozess umgeleitet. Ich denke über die Verwendung von NGINX add-header Befehl, aber konnte es den filename="xx" Teil setzen ?. Oder gibt es eine Möglichkeit, die Anfrage in Django zu bearbeiten, aber NGINX den Inhalt bereitstellen zu lassen?

Antwort

10

Wenn Ihre Django App von Nginx Proxy ist, können Sie x-accell-redirect verwenden. Sie müssen einen speziellen Header in Ihrer Antwort übergeben, nginx fängt dies ab und beginnt mit dem Versenden der Datei. Sie können auch Content-Disposition in derselben Antwort übergeben, um einen Download zu erzwingen.

Diese Lösung ist gut, wenn Sie steuern möchten, welche Benutzer auf diese Dateien zugreifen.

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; 
     } 

     if ($filename ~* ^.*?\.(jpg)|(png)|(gif)$){ 
         add_header Content-Disposition "attachment; filename=$filename"; 
        } 
     } 

    location /static { 
     root /project_root; 
    } 

Dieser Download auf alle Bilder in einigen loestes Ordner (mediaroot/high_rest) zwingen wird. Und für die anderen statischen Dateien verhält es sich wie normal. Bitte beachten Sie, dass dies ein modifizierter schneller Hack ist, der für mich funktioniert. Es kann Auswirkungen auf die Sicherheit haben, also verwenden Sie es mit Vorsicht.

+0

großartig! genau das was ich gesucht habe. – Javier

+0

Fehle ich etwas oder ist das *? redundant? Du könntest es einfach benutzen. * Wenn es Perl Regex ist. –

4

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 anzeigen Bilder, zum Beispiel), und Download-Link.

0

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 weiß nicht wirklich wie der Geruch von ihm.

Verwandte Themen