教育行業(yè)A股IPO第一股(股票代碼 003032)

全國咨詢/投訴熱線:400-618-4000

怎樣解決瀏覽器下載Django項(xiàng)目大文件報(bào)錯(cuò)的問題?

更新時(shí)間:2021年05月13日16時(shí)10分 來源:傳智教育 瀏覽次數(shù):

傳智教育-一樣的教育,不一樣的品質(zhì)


(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
  • 再次優(yōu)化的文件下載功能

上面的代碼已經(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路由配置方法和注意問題詳解

使用Django中間件的六種方法[python培訓(xùn)]

Django海量數(shù)據(jù)集分頁優(yōu)化方法

傳智教育python+大數(shù)據(jù)開發(fā)培訓(xùn)

0 分享到:
和我們在線交談!