Python/Django 大文件下载问题

    最近使用Python/Django开发一个系统,暂且称之为A系统,卡在大文件下载上面,查询了django官方doc和stackoverflow上的很多资料,最终圆满解决此问题,如下为具体过程:


一 A系统中的文件下载

    首先是在view中定义查询方法,在网站上点击查询按钮后,由后台生成相应的数据文件,并将文件名暂存cookie中;

    然后在在view中定义下载方法,采用FileWaper的方式,将文件打包为object,并返回response:

    参考链接:http://stackoverflow.com/questions/1156246/having-django-serve-downloadable-files

1 response = HttpResponse(mimetype='application/force-download')
2 response['Content-Disposition'] = 'attachment; filename=%s' % smart_str(file_name)
3 response['X-Sendfile'] = smart_str(path_to_file)
4 # It's usually a good idea to set the 'Content-Length' header too.
5 # You can also set any other required headers: Cache-Control, etc.
6 return response
View Code

二 遇到的问题与解决方法

    在template中配置好相应的内容,点击查询按钮,查出结果,然后点击下载按钮,问题来了,下载出来一个空文件;随即又多方查找,最后试验到另一个有效的下载方法:

    参考链接:https://djangosnippets.org/snippets/365/

 1 import os, tempfile, zipfile
 2 from django.http import HttpResponse
 3 from django.core.servers.basehttp import FileWrapper
 4 
 5 
 6 def send_file(request):
 7     """                                                                         
 8     Send a file through Django without loading the whole file into              
 9     memory at once. The FileWrapper will turn the file object into an           
10     iterator for chunks of 8KB.                                                 
11     """
12     filename = __file__ # Select your file here.                                
13     wrapper = FileWrapper(file(filename))
14     response = HttpResponse(wrapper, content_type='text/plain')
15     response['Content-Length'] = os.path.getsize(filename)
16     return response
17 
18 
19 def send_zipfile(request):
20     """                                                                         
21     Create a ZIP file on disk and transmit it in chunks of 8KB,                 
22     without loading the whole file into memory. A similar approach can          
23     be used for large dynamic PDF files.                                        
24     """
25     temp = tempfile.TemporaryFile()
26     archive = zipfile.ZipFile(temp, 'w', zipfile.ZIP_DEFLATED)
27     for index in range(10):
28         filename = __file__ # Select your files here.                           
29         archive.write(filename, 'file%d.txt' % index)
30     archive.close()
31     wrapper = FileWrapper(temp)
32     response = HttpResponse(wrapper, content_type='application/zip')
33     response['Content-Disposition'] = 'attachment; filename=test.zip'
34     response['Content-Length'] = temp.tell()
35     temp.seek(0)
36     return response
View Code

    但又出问题了,有的时候可以正常下载,有的时候下载出来也是一个空文件。经过多个参数的调试,终于发现规律,小文件下载没问题,大文件下载下来就是空的,这可真是奇怪。

    随后参考链接中的回复,将如下一行:

    wrapper = FileWrapper(file(filename))         修改为:

    wrapper = FileWrapper(open(filename, 'rb'))

    然后抱着试试看的态度,试了一下,没想到,it works!!!

-------------------------------------------

个性签名:Less is More!

如果觉得这篇文章对你有小小的帮助的话,记得在右下角点个“推荐”哦,博主在此感谢!

从前写代码的时候,总想着测试,测试的时候,总想着用户体验;如今写代码的时候只写代码,测试的时候只测试,至于用户体验,那是后话 ^_^

原文地址:https://www.cnblogs.com/chrisma/p/4169237.html