django|django 下载文件的几种方法

转自:http://blog.sciencenet.cn/blog-47522-664541.html

【django|django 下载文件的几种方法】
django 下载文件的几种方法 from:http://oldj.net/article/django-big-file-response/
from:http://www.douban.com/group/topic/17856825/
from:http://hi.baidu.com/acmtiger/blog/item/e4e5b1874f529bb10df4d2b4.html
1、直接read/yeild返回给客户端
但 Django 中还没有实现对应的方法。一个解决办法是先将要传送的内容全生成在内存中,然后再一次性传入 HttpResponse,比如:

f =open(filename)
data = https://www.it610.com/article/f.read()
f.close()
#以下设置项是为了下载任意类型文件
response = HttpResponse(data,mimetype='application/octet-stream')
response['Content-Disposition'] = 'attachment; filename=%s' %filename
return response
这样处理最简单粗暴,但也存在很大的问题,如果这个文件非常大,这样处理可能会占用大量的内存,甚至导致服务器崩溃。
不过 Django 的开发者应该也考虑到了这种情况,官方文档中提到,可以给 HTTPResponse 传入一个迭代器,同时,StackOverflow上也有一个讨论这个问题的页面。根据这两个页面的内容,上面这个下载大文件的问题可以这样解决:
def bigFileView(request):
# do something...

def readFile(fn, buf_size=262144):
f = open(fn, "rb")
while True:
c = f.read(buf_size)
if c:
yield c
else:
break
f.close()

file_name = "big_file.txt"
response = HttpResponse(readFile(file_name))

return response
 虽然这和其它语言中的 flush 不太一样,并且也并不是每次 yield 时客户端都会收到相应的内容(可能是因为服务器或客户端的缓冲),但这样的方法的确可以解决大文件或大内容下载的问题。经测试,使用这样的方法下载大文件时,服务器的内存占用几乎没有变化。

2、配置用户直接下载文件
经过urls.py的文件, 配置对应下载地址
e.g.,
...
(r'^download/(?P.*)$', 'django.views.static.serve', {'document_root': your_download_path, 'show_indexes':True}),
...
http://xxxxx/download/a.txt

3、下载大文件和压缩zip文件
01.import os, tempfile, zipfile
02.from django.http import HttpResponse
03.from django.core.servers.basehttp import FileWrapper
04.
05.
06.def send_file(request):
07."""
08.Send a file through Django without loading the whole file into
09.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


    推荐阅读