Comprimir archivos en la vista Django y servirlos

En primer lugar, quiero decir que sé que es malo servir archivos desde django, pero mi situación solo puede ser manejada por django, así que lo elegí para servir archivos comprimidos.

class Documents(models.Model): filename = models.CharField(max_length=100) document = models.FileField(upload_to='docs') allowedGroup = models.ManyToManyField(Group) 

Entonces, cuando un usuario normal inicie sesión, se mostrarán los Documentos que tiene permiso de acuerdo con su grupo. Quiero que el usuario pueda descargar varios Documentos (archivos) de una vez. Así que lo que hice se agrega a este controlador. para descargar varios archivos como un archivo zip:

Utilicé este fragmento de Django para crear esta vista

  def Download_selected_document(self, request, queryset): if len(queryset)>1: temp = tempfile.TemporaryFile() archive = zipfile.ZipFile(temp, 'w', zipfile.ZIP_DEFLATED) for i in queryset: ##Reading the file content content = open(settings.MEDIA_ROOT+str(i.document),'rb').read() ##name is name of file like "abc.docx" name = str(queryset[0].document)[10:] ##At this like it gives me error archive.write(content,name) archive.close() wrapper = FileWrapper(temp) response = HttpResponse(wrapper, content_type='application/zip') response['Content-Disposition'] = 'attachment; filename=test.zip' response['Content-Length'] = temp.tell() temp.seek(0) return response else: self.message_user(request, "You must select multiple documents for downloading.") 

El error que obtuve es: debe ser una cadena codificada sin NULL bytes, no str

 Traceback: File "C:\Python27\lib\site-packages\django\core\handlers\base.py" in get_response 111. response = callback(request, *callback_args, **callback_kwargs) File "C:\Python27\lib\site-packages\django\contrib\admin\options.py" in wrapper 307. return self.admin_site.admin_view(view)(*args, **kwargs) File "C:\Python27\lib\site-packages\django\utils\decorators.py" in _wrapped_view 93. response = view_func(request, *args, **kwargs) File "C:\Python27\lib\site-packages\django\views\decorators\cache.py" in _wrapped_view_func 79. response = view_func(request, *args, **kwargs) File "C:\Python27\lib\site-packages\django\contrib\admin\sites.py" in inner 197. return view(request, *args, **kwargs) File "C:\Python27\lib\site-packages\django\utils\decorators.py" in _wrapper 28. return bound_func(*args, **kwargs) File "C:\Python27\lib\site-packages\django\utils\decorators.py" in _wrapped_view 93. response = view_func(request, *args, **kwargs) File "C:\Python27\lib\site-packages\django\utils\decorators.py" in bound_func 24. return func(self, *args2, **kwargs2) File "C:\Python27\lib\site-packages\django\contrib\admin\options.py" in changelist_view 1079. response = self.response_action(request, queryset=cl.get_query_set()) File "C:\Python27\lib\site-packages\django\contrib\admin\options.py" in response_action 836. response = func(self, request, queryset) File "C:\Documents and Settings\Anshul\Desktop\online.in\online\..\online\assessment\admin.py" in Download_selected_document 82. archive.write(content,name) File "C:\Python27\lib\zipfile.py" in write 1031. st = os.stat(filename) Exception Type: TypeError at /admin/assessment/userdocuments/ Exception Value: must be encoded string without NULL bytes, not str 

No sé cómo debo arreglar esto. Por favor ayuda

Utilizar

 zipfile.ZipFile().writestr(archived_name, content_to_be_archived) 

en lugar de

 zipfile.ZipFile().write(filename_to_load_content_from, archived_name=None) 

Así que una solución rápida podría ser

 archive.write(content,name) => archive.writestr(name, content) 

Además, es posible que desee comprobar

  • StringIO en lugar de tempfile si el tamaño del archivo comprimido es normalmente pequeño
  • Dado que el objeto HttpResponse es un objeto similar a un archivo, usted podría comprimirlo directamente
  • Use XSendfile o X-Accel-Redirect en nginx para ayudar a transferir el archivo respondido en lugar de confiar en el propio Django