Quiero que los usuarios del sitio puedan descargar archivos cuyas rutas están oscurecidas para que no se puedan descargar directamente.
Por ejemplo, me gustaría que la URL sea algo así: http://example.com/download/?f=somefile.txt
Y en el servidor, sé que todos los archivos descargables residen en la carpeta /home/user/files/
.
¿Hay alguna manera de hacer que Django sirva ese archivo para descargar en lugar de intentar encontrar una URL y Ver para mostrarlo?
Respuestas:
Para "lo mejor de ambos mundos", podría combinar la solución de S.Lott con el módulo xsendfile : django genera la ruta al archivo (o el archivo en sí), pero Apache / Lighttpd maneja el servicio del archivo real. Una vez que haya configurado mod_xsendfile, la integración con su vista requiere algunas líneas de código:
Por supuesto, esto solo funcionará si tiene control sobre su servidor, o si su empresa de alojamiento ya ha configurado mod_xsendfile.
EDITAR:
EDITAR: Para
nginx
verificar esto , usa enX-Accel-Redirect
lugar delapache
encabezado X-Sendfile.fuente
smart_str
no funciona según lo previsto ya que el módulo apache X-Sendfile no puede decodificar la cadena codificada smart_str. Así, por ejemplo, el archivo "Örinää.mp3" no se puede servir. Y si uno omite smart_str, el Django arroja un error de codificación ASCII porque todos los encabezados están codificados en formato ASCII antes de enviarlos. La única forma que conozco para sortear este problema es reducir los nombres de archivos X-sendfile a los que consisten solo en ascii.Una "descarga" es simplemente un cambio de encabezado HTTP.
Ver http://docs.djangoproject.com/en/dev/ref/request-response/#telling-the-browser-to-treat-the-response-as-a-file-attachment para saber cómo responder con una descarga .
Solo necesita una definición de URL para
"/download"
.La solicitud
GET
o elPOST
diccionario tendrán la"f=somefile.txt"
información.Su función de vista simplemente fusionará la ruta base con el
f
valor " ", abrirá el archivo, creará y devolverá un objeto de respuesta. Debe tener menos de 12 líneas de código.fuente
filepath = filepath.replace('..', '').replace('/', '')
Para una solución muy simple pero no eficiente o escalable , puede usar la
serve
vista integrada de django . Esto es excelente para prototipos rápidos o trabajos únicos, pero como se ha mencionado a lo largo de esta pregunta, debe usar algo como apache o nginx en la producción.fuente
S.Lott tiene la solución "buena" / simple, y elo80ka tiene la "mejor" / solución eficiente. Aquí hay una solución "mejor" / intermedia: sin configuración del servidor, pero más eficiente para archivos grandes que la solución ingenua:
http://djangosnippets.org/snippets/365/
Básicamente, Django todavía maneja el servicio del archivo pero no carga todo en la memoria de una vez. Esto permite que su servidor sirva (lentamente) un archivo grande sin aumentar el uso de memoria.
Una vez más, X-SendFile de S.Lott es aún mejor para archivos más grandes. Pero si no puede o no quiere molestarse con eso, entonces esta solución intermedia le brindará una mayor eficiencia sin la molestia.
fuente
django.core.servers.httpbase
módulo privado indocumentado, que tiene una gran señal de advertencia en la parte superior del código " ¡NO USAR PARA USO DE PRODUCCIÓN! ", Que ha estado en el archivo desde que se creó por primera vez . En cualquier caso, laFileWrapper
funcionalidad en la que se basa este fragmento se ha eliminado en django 1.9.Intenté la solución @Rocketmonkeys pero los archivos descargados se almacenaron como * .bin y se les dio nombres aleatorios. Eso no está bien, por supuesto. Agregar otra línea de @ elo80ka resolvió el problema.
Aquí está el código que estoy usando ahora:
Ahora puede almacenar archivos en un directorio privado (no dentro de / media ni / public_html) y exponerlos a través de django a ciertos usuarios o bajo ciertas circunstancias.
Espero eso ayude.
Gracias a @ elo80ka, @ S.Lott y @Rocketmonkeys por las respuestas, obtuve la solución perfecta combinando todas ellas =)
fuente
filename="%s"
en el encabezado Content-Disposition para evitar problemas con espacios en los nombres de archivo. Referencias: los nombres de archivo con espacios se truncan al descargarlos . ¿Cómo codificar el parámetro de nombre de archivo del encabezado Content-Disposition en HTTP?FileWrapper(open(path.abspath(file_name), 'rb'))
FileWrapper
ha sido eliminado desde Django 1.9from wsgiref.util import FileWrapper
Solo menciono el objeto FileResponse disponible en Django 1.10
Editar: acabo de encontrar mi propia respuesta mientras buscaba una manera fácil de transmitir archivos a través de Django, así que aquí hay un ejemplo más completo (para mí en el futuro). Se supone que el nombre de FileField es
imported_file
views.py
urls.py
fuente
Se mencionó anteriormente que el método mod_xsendfile no permite caracteres no ASCII en los nombres de archivo.
Por esta razón, tengo un parche disponible para mod_xsendfile que permitirá enviar cualquier archivo, siempre que el nombre esté codificado en url y el encabezado adicional:
También se envía.
http://ben.timby.com/?p=149
fuente
Prueba: https://pypi.python.org/pypi/django-sendfile/
"Abstracción para descargar archivos subidos al servidor web (por ejemplo, Apache con mod_xsendfile) una vez que Django haya verificado los permisos, etc."
fuente
Debe usar las apis sendfile proporcionadas por servidores populares como
apache
onginx
en producción. Muchos años estuve usando sendfile api de estos servidores para proteger archivos. Luego creó una aplicación django basada en middleware simple para este propósito, adecuada tanto para el desarrollo como para la producción. Puede acceder al código fuente aquí .ACTUALIZACIÓN: en la nueva versión, el
python
proveedor usa djangoFileResponse
si está disponible y también agrega soporte para muchas implementaciones de servidor desde lighthttp, caddy hasta hiawathaUso
fileprovider
aplicación a laINSTALLED_APPS
configuración,fileprovider.middleware.FileProviderMiddleware
a laMIDDLEWARE_CLASSES
configuraciónFILEPROVIDER_NAME
configuraciones ennginx
oapache
en producción, por defecto espython
para fines de desarrollo.en sus vistas de clase o función establezca el
X-File
valor del encabezado de respuesta en la ruta absoluta al archivo. Por ejemplo,django-fileprovider
Se ha implementado de manera tal que su código solo necesitará una modificación mínima.Configuración de Nginx
Para proteger el archivo del acceso directo, puede establecer la configuración como
Aquí
nginx
establece una dirección URL de/files/
acceso solo internamente, si está utilizando la configuración anterior, puede configurar X-File como,Al hacer esto con la configuración nginx, el archivo estará protegido y también puede controlar el archivo desde django
views
fuente
Django recomienda que use otro servidor para servir medios estáticos (otro servidor que se ejecuta en la misma máquina está bien). Recomienda el uso de servidores como lighttp .
Esto es muy simple de configurar. Sin embargo. si se genera 'somefile.txt' a pedido (el contenido es dinámico), entonces es posible que desee que django lo sirva.
Django Docs - Archivos estáticos
fuente
fuente
Otro proyecto para echar un vistazo: http://readthedocs.org/docs/django-private-files/en/latest/usage.html Parece prometedor, aunque todavía no lo he probado.
Básicamente, el proyecto abstrae la configuración mod_xsendfile y le permite hacer cosas como:
fuente
django-private-files
...Me he enfrentado al mismo problema más de una vez y lo implementé usando el módulo xsendfile y los decoradores de vista de autenticación django-filelibrary . Siéntase libre de usarlo como inspiración para su propia solución.
https://github.com/danielsokolowski/django-filelibrary
fuente
Proporcionar acceso protegido a la carpeta estática html usando https://github.com/johnsensible/django-sendfile : https://gist.github.com/iutinvg/9907731
fuente
Hice un proyecto sobre esto. Puedes mirar mi repositorio github:
https://github.com/nishant-boro/django-rest-framework-download-expert
Este módulo proporciona una manera simple de servir archivos para descargar en django rest framework usando el módulo Apache Xsendfile. También tiene una función adicional de servir descargas solo a usuarios que pertenecen a un grupo en particular
fuente