更新時(shí)間:2021年05月13日16時(shí)10分 來源:傳智教育 瀏覽次數(shù):
(1)問題分析
面試官主要想考察的是Django項(xiàng)目大文件下載,大多數(shù)瀏覽器不支持,容易報(bào)錯(cuò),該怎么解決。
(2)核心問題講解
基本的文件下載功能
def file_download(request):
# do something
with open('file_name.txt') as file:
c = file.read()
return HttpResponse(c)
以上這種方式簡單粗暴,適合小文件的下載,但文件非常大,這種方式會(huì)占用大量的內(nèi)存,甚至導(dǎo)致服務(wù)器崩潰,因此需要采用更加合理的方式。
Django的HttpResponse對象允許將迭代器作為傳入?yún)?shù),將上面代碼中的傳入?yún)?shù)c換成一個(gè)迭代器,便可以將上述下載功能優(yōu)化為對大小文件均適合;而Django更進(jìn)一步,推薦使用 StreamingHttpResponse對象取代HttpResponse對象,StreamingHttpResponse對象用于將文件流發(fā)送給瀏覽器,與HttpResponse對象非常相似,對于文件下載功能,使用StreamingHttpResponse對象更合理。
因此,更加合理的文件下載功能,應(yīng)該先寫一個(gè)迭代器,用于處理文件,然后將這個(gè)迭代器作為參數(shù)傳遞給StreaminghttpResponse對象,代碼如下:
from django.http import StreamingHttpResponse
def big_file_download(request):
# do something
def file_iterator(file_name, chunk_size=512):
whth open(file_name) as file:
while True:
c = file.read(chunk_size)
if c:
yield c
else:
break
the_file_name = "file_name.txt"
response = StreamingHttpResponse(file_iterator(the_file_name))
return response
上面的代碼已經(jīng)完成了將服務(wù)器上的文件,通過文件流傳輸?shù)綖g覽器,但文件流通常會(huì)以亂碼形式顯示到瀏覽器中,而非下載到硬盤上,因此還要進(jìn)行一些優(yōu)化,讓文件流寫入硬盤。以上代碼的優(yōu)化方式很簡單,直接給StreamingHttpResponse對象的Content-Type和Content-Disposition字段賦下面的值即可,改后的代碼如下:
response['Content-Type'] = 'application/octet-stream'
response['Content-Disposition'] = 'attachment;filename="test.pdf"'
完整代碼如下:
from django.http import StreamingHttpResponse
def big_file_download(request):
# do something
def file_iterator(file_name, chunk_size=512):
whth open(file_name) as file:
while True:
c = file.read(chunk_size)
if c:
yield c
else:
break
the_file_name = "big_file.pdf"
response = StreamingHttpResponse(file_iterator(the_file_name))
response['Content-Type'] = 'application/octet-stream'
response['Content-Disposition'] = 'attachment;filename="{0}"'.format(the_file_name)
return response
(3)問題擴(kuò)展
無
(4)結(jié)合項(xiàng)目中使用
Django項(xiàng)目大文件下載,大多數(shù)瀏覽器不支持,容易報(bào)錯(cuò)。
使用Django中間件的六種方法[python培訓(xùn)]
北京校區(qū)