2008-11-04 11 views
9

Estoy escribiendo un banco de imágenes con Django, y quiero agregar un botón para obtener una versión de alta resolución de una imagen (la baja resolución se muestra en la página de detalles) . Si pongo solo un enlace <a>, el navegador abrirá la imagen en lugar de descargarla. La adición de una cabecera HTTP como:encabezados HTTP personalizados para archivos estáticos con Django

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

obras, pero ya que es un archivo estático, no quiero para manejar la petición con Django. Actualmente, estoy usando NGINX para servir archivos estáticos, y las páginas dinámicas se redirigen a través de FastCGI al proceso de Django. Estoy pensando en usar el comando NGINX add-header, pero ¿podría establecer la parte filename="xx" ?. ¿O tal vez hay alguna forma de manejar la solicitud en Django, pero hacer que NGINX sirva el contenido?

Respuesta

10

Si su aplicación django está proxys por nginx puede usar x-accell-redirect. Debe pasar un encabezado especial en su respuesta, nginx lo interceptará y comenzará a servir el archivo, también puede pasar Content-Disposition en la misma respuesta para forzar una descarga.

Esa solución es buena si desea controlar qué usuarios acceden a estos archivos.

También se puede utilizar una configuración como esta:

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

Esto obligará a su descarga en todas las imágenes en alguna carpeta high_res (mediaroot/high_rest). Y para los demás archivos estáticos, se comportará de forma normal. Tenga en cuenta que este es un truco rápido modificado que funciona para mí. Puede tener implicaciones de seguridad, así que úselo con precaución.

+0

genial! Exactamente lo que estaba buscando. – Javier

+0

¿Me falta algo o es. *? ¿redundante? Podrías usar. * Si es perl regex. –

4

me escribió un decorador sencilla, por django.views.static.serve vista

que funciona perfectamente para mí.

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 

También se puede jugar con nginx tipos MIME

http://wiki.codemongers.com/NginxHttpCoreModule#types

Esta solución no funcionó para mí, porque yo quería tener relación directa tanto para el archivo (por lo que el usuario puede ver imágenes, por ejemplo) y enlace de descarga.

0

lo que estoy haciendo ahora es usar una URL diferente para su descarga que para los puntos de vista '', y añadir el nombre de archivo como arg URL:

habitual de enlace de medios: http://xx.com/media/images/lores/f_123123.jpg enlace de descarga: http://xx.com/downs/hires/f_12323?beach008.jpg

y nginx tiene una configuración como esta:

location /downs/ { 
     root /var/www/nginx-attachment; 
     add_header Content-Disposition 'attachment; filename="$args"'; 
    } 

pero realmente no les gusta el olor de ella.

Cuestiones relacionadas