在Django视图中压缩文件并提供它们 [英] Zipping files in Django view and serving them

查看:141
本文介绍了在Django视图中压缩文件并提供它们的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

首先我想说,我知道它的django文件服务不好,但我的情况只能由django处理,所以我选择它来提供压缩文件。在我的models.py我有一个模型

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

所以当一个正常的用户登录时,它将被显示他根据他/她的组的权限的文档。我希望用户能够一次下载多个文档(文件)。所以我做的是添加这个处理程序将多个文件作为zip文件下载:



我使用这个 Django Snippet 创建此视图

  def Download_selected_document(self,request,queryset):

如果len(queryset)> 1:

temp = tempfile.TemporaryFile()
archive = zipfile.ZipFile(temp,'w',zipfile.ZIP_DEFLATED)
对于我在查询中:
##读取文件内容
content = open(settings.MEDIA_ROOT + str(i.document),'rb')。read()
## name是abc.docx的文件名称
name = str(queryset [ 0] .document)[10:]
##这样就可以给我错误
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)
返回响应

其他:
self.message_user(请求,您必须选择多个文件才能下载。)

我得到的错误是:必须是不带NULL字节的编码字符串,而不是str

 追溯:
文件C:\Python27\lib\site-packages\django\core\handlers\base.pyin get_response
111. response = callback(request,* callback_args,* * callback_kwargs)
文件C:\Python27\lib\site- packages\django\contrib\admin\options.py在包装器
307. return self.admin_site。 admin_view(view)(* args,** kwargs)
文件C:\Python27\lib\site-packages\django\utils\decorators.py在_wrapped_view
93 。response = view_fun c(request,* args,** kwargs)
在_wrapped_view_func中的文件C:\Python27\lib\site- packages\django\views\decorators\cache.py
79. response = view_func(request,* args,** kwargs)
文件C:\Python27\lib\site- packages\django\contrib\admin\sites.py在内部
197. return view(request,* args,** kwargs)
文件C:\Python27\lib\site-packages\django\utils\decorators.py in _wrapper
28. return bound_func(* args,** kwargs)
文件C:\Python27\lib\site- packages\django\utils\decorators.py在_wrapped_view
93. response = view_func(request,* args,** kwargs)
文件C:\Python27\lib\site- packages\django\utils\decorators。 pyin bound_func
24. return func(self,* args2,** kwargs2)
文件C:\Python27\lib\site-packages \\ django\contrib\admin\options.pyin changelist_view
1079. response = self.response_action(request,queryset = cl.get_query_set())
文件C:\Python27 \\ \\ lib\site- packages\django\contrib\admin\options.pyin response_action
836. response = func(self,request,queryset)
文件C:\文件和设置\Anshul\Desktop\online.in\online\..\online\assessment\admin.py在Download_selected_document
82. archive.write(content,name)
文件C:\Python27\lib\zipfile.py中写入
1031. st = os.stat(filename)

异常类型:TypeError at / admin / assessment / userdocuments /
异常值:必须是不带NULL字节的编码字符串,而不是str

我不知道该怎么解决这个问题。请帮助

解决方案

使用

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

/ p>

  zipfile.ZipFile()。write(filename_to_load_content_from,archived_name = None)
pre>

所以快速修复可能是

  archive.write(内容,名称)=> archive.writestr(name,content)

此外,您可能想查看




  • 如果压缩文件的大小通常很小,则StringIO而不是tempfile

  • 由于HttpResponse对象是类文件对象,您可以直接使用它来压缩

  • 在nginx中使用XSendfile或X-Accel-Redirect来帮助传输响应文件,而不是依赖于Django本身


    • First of all I want to say that I know its bad to serve files from django but my situation can only be handled by django so I chose it to serve zipped files.In my models.py I have a model

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

      So when a normal user log-in it will be displayed the Documents which he has permission according to his/her group.I want user to be able to download multiple Documents(files) at one go.So what I did is added this handler for downloading multiple files as a zip file:

      I used this Django Snippet for creating this view

        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.")
      

      Error I got is : must be encoded string without NULL bytes, not 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
      

      I dont know how should I fix this.Please help

      解决方案

      Use

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

      instead of

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

      So a quick fix might be

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

      Furthermore, you may want to check

      • StringIO instead of tempfile if the size of zipped file is normally small
      • Since HttpResponse object is a file-like object, you could zip to it directly
      • Use XSendfile, or X-Accel-Redirect in nginx to help transferring the responded file instead of relying on Django itself

      这篇关于在Django视图中压缩文件并提供它们的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆