2010-04-22 13 views
15

Así que, por supuesto, sé que el servicio de archivos estáticos a través de Django te enviará directo al infierno, pero estoy confundido sobre cómo usar una url personalizada para enmascarar la verdadera ubicación del archivo usando Django. Django: Serving a Download in a Generic View pero la respuesta que acepté parece ser la forma "incorrecta" de hacer las cosas.Django: Serving Media Behind Custom URL

urls.py:

url(r'^song/(?P<song_id>\d+)/download/$', song_download, name='song_download'), 

views.py:

def song_download(request, song_id): 
    song = Song.objects.get(id=song_id) 
    fsock = open(os.path.join(song.path, song.filename)) 

    response = HttpResponse(fsock, mimetype='audio/mpeg') 
    response['Content-Disposition'] = "attachment; filename=%s - %s.mp3" % (song.artist, song.title) 

    return response 

Esta solución funciona perfectamente pero no lo suficiente perfectamente resulta. ¿Cómo puedo evitar tener un enlace directo al mp3 mientras sigo sirviendo a través de nginx/apache?

EDIT 1 - INFORMACIÓN ADICIONAL

la actualidad que esté en mis archivos mediante el uso de una dirección como: http://www.example.com/music/song/1692/download/ Pero el método antes mencionado es el trabajo del diablo.

¿Cómo puedo lograr lo que obtengo arriba mientras sigo haciendo que nginx/apache sirva los medios? ¿Esto es algo que debería hacerse a nivel del servidor web? ¿Algún mod_rewrite loco?

http://static.example.com/music/Aphex%20Twin%20-%20Richard%20D.%20James%20(V0)/10%20Logon-Rock%20Witch.mp3

EDIT 2 - INFORMACIÓN ADICIONAL ADICIONAL

uso nginx para mi frontend y proxy inverso volver servidor Apache/desarrollo así que creo que si se requiere un cierto tipo de trabajo mod_rewrite tendré para encontrar algo que funcione con nginx.

Respuesta

15

Para ampliar las respuestas anteriores, debe poder modificar el siguiente código y hacer que nginx sirva directamente sus archivos de descarga mientras que aún tiene los archivos protegidos.

En primer lugar añadir una ubicación, como:

location /files/ { 
    alias /true/path/to/mp3/files/; 
    internal; 
} 

a su archivo nginx.conf (el interno hace que este no es directamente accesible). Entonces necesita una vista de Django algo como esto:

def song_download(request, song_id): 
    try: 
     song = Song.objects.get(id=song_id) 
     response = HttpResponse() 
     response['Content-Type'] = 'application/mp3' 
     response['X-Accel-Redirect'] = '/files/' + song.filename 
     response['Content-Disposition'] = 'attachment;filename=' + song.filename 
    except Exception: 
     raise Http404 
    return response 

que entregará la descarga del archivo a nginx.

+0

Esto es más o menos exactamente lo que necesitaba, ¡gracias! – TheLizardKing

+0

Gracias a los dos. ¡He estado buscando un tiempo para esa solución y estaba haciendo mucho ruido! – Sebastien

1

Ambos httpd y tienen una forma de especificar un archivo estático para que se sirva a través de un encabezado. Sin embargo, el encabezado exacto varía, por lo que es mejor poner algo en la configuración para elegir el método.

3

La idea básica es hacer que su vista de Django redirija a una URL segura atendida por su servidor de medios.

Ver this list de sugerencias de Graham Dumpleton, autor de mod_wsgi.