python instalar - Que Django sirva archivos descargables




7 Answers

Para "lo mejor de los dos mundos", puede 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 archivo real. Una vez que haya configurado mod_xsendfile, la integración con su vista toma algunas líneas de código:

from django.utils.encoding import smart_str

response = HttpResponse(mimetype='application/force-download') # mimetype is replaced by content_type for django 1.7
response['Content-Disposition'] = 'attachment; filename=%s' % smart_str(file_name)
response['X-Sendfile'] = smart_str(path_to_file)
# It's usually a good idea to set the 'Content-Length' header too.
# You can also set any other required headers: Cache-Control, etc.
return response

Por supuesto, esto solo funcionará si usted tiene control sobre su servidor, o si su compañía de alojamiento ya ha configurado mod_xsendfile.

EDITAR:

mimetype es reemplazado por content_type para django 1.7

response = HttpResponse(content_type='application/force-download'  

EDITAR: Para nginx verifique this , usa X-Accel-Redirect lugar del encabezado de apache X-Sendfile.

en windows

Quiero que los usuarios del sitio puedan descargar archivos cuyas rutas estén ocultas para que no puedan descargarse directamente.

Por ejemplo, me gustaría que la URL fuera algo como esto ", http://example.com/download/?f=somefile.txt

Y en el servidor, sé que todos los archivos descargables residen en una carpeta "/ home / user / files /".

¿Hay alguna manera de hacer que Django sirva ese archivo para descargarlo en lugar de intentar encontrar una URL y Ver para mostrarlo?




S.Lott tiene la solución "buena" / simple, y elo80ka tiene la solución "mejor" / eficiente. Aquí hay una solución "mejor" / intermedia: no hay configuración del servidor, pero es más eficiente para archivos grandes que la solución ingenua:

http://djangosnippets.org/snippets/365/

Básicamente, Django aún maneja el 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 la memoria.

Nuevamente, el archivo X-SendFile de S.Lott sigue siendo mejor para archivos más grandes. Pero si no puedes o no quieres molestarte con eso, entonces esta solución intermedia te dará una mayor eficiencia sin la molestia.




Probé la solución @Rocketmonkeys pero los archivos descargados se almacenaron como * .bin y se les dieron nombres aleatorios. Eso no está bien, por supuesto. Añadir otra línea de @ elo80ka solucionó el problema.
Aquí está el código que estoy usando ahora:

from wsgiref.util import FileWrapper
from django.http import HttpResponse

filename = "/home/-addict/private-folder(not-porn)/image.jpg"
wrapper = FileWrapper(file(filename))
response = HttpResponse(wrapper, content_type='text/plain')
response['Content-Disposition'] = 'attachment; filename=%s' % os.path.basename(filename)
response['Content-Length'] = os.path.getsize(filename)
return response

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 combinándolas todas =)




Solo mencionando el objeto FileResponse disponible en Django 1.10

Edición: Me topé con mi propia respuesta mientras buscaba una forma 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

vistas.py

from django.views.generic.detail import DetailView   
from django.http import FileResponse
class BaseFileDownloadView(DetailView):
  def get(self, request, *args, **kwargs):
    filename=self.kwargs.get('filename', None)
    if filename is None:
      raise ValueError("Found empty filename")
    some_file = self.model.objects.get(imported_file=filename)
    response = FileResponse(some_file.imported_file, content_type="text/csv")
    # https://docs.djangoproject.com/en/1.11/howto/outputting-csv/#streaming-large-csv-files
    response['Content-Disposition'] = 'attachment; filename="%s"'%filename
    return response

class SomeFileDownloadView(BaseFileDownloadView):
    model = SomeModel

urls.py

...
url(r'^somefile/(?P<filename>[-\w_\\-\\.]+)$', views.SomeFileDownloadView.as_view(), name='somefile-download'),
...



Debe usar las apis de sendfile dadas por servidores populares como apache o nginx en producción. Durante muchos años, estuve usando la aplicación sendfile de estos servidores para proteger archivos. Luego creó una aplicación django sencilla basada en middleware para este propósito, adecuada tanto para desarrollo como para producción. here puede acceder al código fuente.
ACTUALIZACIÓN: en la nueva versión, el proveedor de python usa django FileResponse si está disponible y también agrega soporte para muchas implementaciones de servidores desde lighthttp, caddy a hiawatha

Uso

pip install django-fileprovider
  • agrega la aplicación fileprovider a la configuración de INSTALLED_APPS ,
  • agregar fileprovider.middleware.FileProviderMiddleware a la configuración de MIDDLEWARE_CLASSES
  • establezca la configuración de FILEPROVIDER_NAME en nginx o apache en producción, de forma predeterminada es python para fines de desarrollo.

en sus vistas basadas en clases o funciones, establezca el valor del X-File encabezado de respuesta en la ruta absoluta al archivo. Por ejemplo,

def hello(request):  
   // code to check or protect the file from unauthorized access
   response = HttpResponse()  
   response['X-File'] = '/absolute/path/to/file'  
   return response  

django-fileprovider mejorado de manera que su código solo necesitará una modificación mínima.

Configuracion nginx

Para proteger el archivo del acceso directo, puede configurar la configuración como

 location /files/ {
  internal;
  root   /home/sideffect0/secret_files/;
 }

Aquí nginx establece una ubicación url /files/ solo acceso interno, si está utilizando la configuración anterior, puede configurar X-File como,

response['X-File'] = '/files/filename.extension' 

Al hacer esto con la configuración de nginx, el archivo estará protegido y también puede controlar el archivo desde las views django




def qrcodesave(request): 
    import urllib2;   
    url ="http://chart.apis.google.com/chart?cht=qr&chs=300x300&chl=s&chld=H|0"; 
    opener = urllib2.urlopen(url);  
    content_type = "application/octet-stream"
    response = HttpResponse(opener.read(), content_type=content_type)
    response["Content-Disposition"]= "attachment; filename=aktel.png"
    return response 



He enfrentado el mismo problema más de una vez y, por lo tanto, lo he implementado utilizando el módulo xsendfile y los decoradores de vistas de autenticación en la django-filelibrary . Siéntase libre de usarlo como inspiración para su propia solución.

django-filelibrary




Related

python django download