django提供文件下載時,若果文件較小,解決辦法是先將要傳送的內(nèi)容全生成在內(nèi)存中,然后再一次性傳入Response對象中:
def simple_file_download(request):
# do something...
content = open("simplefile", "rb").read()
return HttpResponse(content)
如果文件非常大時,最簡單的辦法就是使用靜態(tài)文件服務(wù)器,比如Apache或者Nginx服務(wù)器來處理下載。不過有時候,我們需要對用戶的權(quán)限做一下限定,或者不想向用戶暴露文件的真實地址,或者這個大內(nèi)容是臨時生成的(比如臨時將多個文件合并而成的),這時就不能使用靜態(tài)文件服務(wù)器了。
templates/index.html
<div class="row">
<div class="col-md-8 col-md-offset-2">
<br>
<P>第一種方法,直接把鏈接地址指向要下載的靜態(tài)文件,在頁面中點擊該鏈接,可以直接打開該文件,在鏈接上點擊右鍵,選擇“另存為”可以保存該文件到本地硬盤。
此方法只能實現(xiàn)靜態(tài)文件的下載,不能實現(xiàn)動態(tài)文件的下載。</P>
<a href="{% url 'media' 'uploads/11.png' %}">11.png</a>
<br>
<br>
<p>第二種方法,將鏈接指向相應(yīng)的view函數(shù),在view函數(shù)中實現(xiàn)下載功能,可以實現(xiàn)靜態(tài)和動態(tài)文件的下載。</p>
<a href="{% url 'course:download_file' %}">11.png</a>
<br>
<br>
<br>
<p>第三種方法,與第二種方法類似,利用按鈕的響應(yīng)函數(shù)實現(xiàn)文件下載功能。</p>
<label> 11.png</label><button onclick="window.location.href='{% url 'course:download_file' %}'">Download</button>
</div>
</div>
views.py
def download_file(request):
# do something
the_file_name='xxx.png' #顯示在彈出對話框中的默認(rèn)的下載文件名
filename='media/uploads/xxx.png' #要下載的文件路徑
response=StreamingHttpResponse(readFile(filename))
response['Content-Type']='application/octet-stream'
response['Content-Disposition']='attachment;filename="{0}"'.format(the_file_name)
return response
def readFile(filename,chunk_size=512):
with open(filename,'rb') as f:
while True:
c=f.read(chunk_size)
if c:
yield c
else:
break
python也提供一個文件包裝器,將類文件對象包裝成一個迭代器:(未驗證)
class FileWrapper:
"""Wrapper to convert file-like objects to iterables"""
def __init__(self, filelike, blksize=8192):
self.filelike = filelike
self.blksize = blksize
if hasattr(filelike,'close'):
self.close = filelike.close
def __getitem__(self,key):
data = self.filelike.read(self.blksize)
if data:
return data
raise IndexError
def __iter__(self):
return self
def next(self):
data = self.filelike.read(self.blksize)
if data:
return data
raise StopIteration
使用時views.py的寫法
from django.core.servers.basehttp import FileWrapper
from django.http import HttpResponse
import os
def file_download(request,filename):
wrapper = FileWrapper(file('filepath'))
response = HttpResponse(wrapper, content_type='application/octet-stream')
response['Content-Length'] = os.path.getsize(path) ??????
response['Content-Disposition'] = 'attachment; filename=%s' % filename
return response