2010-03-29 9 views
13

Quiero devolver algunos archivos en una HttpResponse y estoy usando la siguiente función. El archivo que se devuelve siempre tiene un tamaño de archivo de 1 KB y no sé por qué. Puedo abrir el archivo, pero parece que no se sirve correctamente. Por lo tanto, quería saber cómo se pueden devolver los archivos con django/python en una HttpResponse.django return file over HttpResponse - el archivo no se sirve correctamente

@login_required 
def serve_upload_files(request, file_url): 
    import os.path 
    import mimetypes 
    mimetypes.init() 

    try: 
     file_path = settings.UPLOAD_LOCATION + '/' + file_url 
     fsock = open(file_path,"r") 
     #file = fsock.read() 
     #fsock = open(file_path,"r").read() 
     file_name = os.path.basename(file_path) 
     file_size = os.path.getsize(file_path) 
     print "file size is: " + str(file_size) 
     mime_type_guess = mimetypes.guess_type(file_name) 
     if mime_type_guess is not None: 
      response = HttpResponse(fsock, mimetype=mime_type_guess[0]) 
     response['Content-Disposition'] = 'attachment; filename=' + file_name    
    except IOError: 
     response = HttpResponseNotFound() 
    return response 

Editar: El error no es en realidad un error ;-)

Esta solución está trabajando en la producción en un servidor Apache, por tanto, la fuente está bien.

Mientras escribía esta pregunta, la probé localmente con el servidor de desarrollo django y me preguntaba por qué no funciona. Un amigo mío me dijo que este problema podría surgir si los tipos de mime no están configurados en el servidor. Pero no estaba seguro de si este es el problema. Pero una cosa es segura ... tiene algo que ver con el servidor.

+8

Para aquellos que intenten usar este código, tenga en cuenta que el argumento 'mimetype' en' HttpResponse' ha sido reemplazado por el campo 'content_type'. –

Respuesta

9

Intente pasar el iterador fsock como un parámetro a HttpResponse(), en lugar de a su método write() que creo que espera una cadena.

response = HttpResponse(fsock, mimetype=...) 

Ver http://docs.djangoproject.com/en/dev/ref/request-response/#passing-iterators

Además, no estoy seguro de que desea llamar close en su archivo antes de regresar response. Después de haber jugado con esto en el shell (no he probado esto en una vista real de Django), parece que el response no tiene acceso al archivo hasta que se lee el response. Intentar leer un HttpResponse creado con un archivo que ahora está cerrado da como resultado un ValueError: I/O operation on closed file.

Por lo tanto, es posible que desee dejar fsock abierto, y deje que el recolector de basura se ocupe de él después de que se lea la respuesta.

+0

Hola, gracias por tu respuesta. Lamentablemente, no cambia nada. response = HttpResponse (fsock, mimetype = mime_type_guess [0]). El archivo aún no se sirve correctamente. Además, compruebe el tamaño del archivo (con file_size = os.path.getsize (file_path) print "el tamaño del archivo es:" + str (tamaño_archivo)) antes de devolverlo a través de HttpResponse y lo devuelve: el tamaño del archivo es: 56349. Por lo tanto, el archivo se lee correctamente desde el sistema de archivos y algo salió mal cuando se devuelve. –

+0

Tom Tom, ver las adiciones a mi respuesta. –

+0

Estoy de acuerdo con Ben. Cuando se agrega fsock a HttpResponse, ya sea en el constructor o usando el método 'write', se agrega a la pila interna de contenido que HttpResponse mantiene. Esa pila no se evalúa hasta más tarde, en el último momento posible cuando la respuesta es realmente necesaria.Tendrá que dejar el fsock abierto o de lo contrario HttpResponse generará un error cuando intente leer de él. El recolector de basura se encargará de cerrar el archivo. –

11

¿Podría ser que el archivo contenga algunos caracteres no ASCII que rinden bien en producción pero no en desarrollo?

Trate de leer el archivo en formato binario:

fsock = open(file_path,"rb") 
+3

¡Eres mi salvador! Todas las publicaciones principales para servir archivos a través de Django no cubren esta necesidad binaria cuando se publica desde Windows. Por cierto, configurar "rb" funciona mientras se usa FileWrapper para servir fragmentos a través de: return HttpResponse (FileWrapper (open (filename, "rb")), content_type = mimetypes.guess_type (filename) [0]) – garromark

1

Intente desactivar "django.middleware.gzip.GZipMiddleware" de sus MIDDLEWARE_CLASSES en settings.py

que tenía el mismo problema, y ​​después miré alrededor de la carpeta de middleware, este middleware parecía culpable para mí y eliminarlo fue lo que hizo.

Cuestiones relacionadas