鍍金池/ 問答/Java  Python/ django 下載文件 無法正常打開

django 下載文件 無法正常打開

問題現(xiàn)象

下載文件,無法正常打開,如下圖

clipboard.png

需手動(dòng)加后綴名修改文件格式方可正常打開
進(jìn)而能得知文件內(nèi)容正常
如下圖,給“下載”文件加上后綴即可得到正常下載的內(nèi)容

clipboard.png

問題整理:(此下載功能采用StreamHttpResponse)

1、已在源碼中指定了下載的文件名:

response['Content-Disposition'] = 'attachment;filename="{f_name}"'.format(f_name=the_file_name)

但結(jié)果下載的文件統(tǒng)一均為“下載”的文件名字

2、下載功能和數(shù)據(jù)內(nèi)容是正常的,應(yīng)該是命名這個(gè)環(huán)節(jié)出錯(cuò),并且文件是含有中文字符,請(qǐng)幫指正。

補(bǔ)充:
python版本 3.6
django版本 1.11.13

完整源碼

from django.http import StreamingHttpResponse
# 切片讀取文件
def file_iterator(filename,chunk_size=512):
    with open(filename,'rb') as f:
        while True:
            c=f.read(chunk_size)
            if c:
                yield c
            else:
                break

# 下載功能
def download_file(request):
    the_file_name = models.FileObj.objects.get(id=request.GET.get("id")).fileName  # 顯示在彈出對(duì)話框中的默認(rèn)的下載文件名
    file_path = os.path.join(file_dir,the_file_name) # 要下載的文件路徑
    response = StreamingHttpResponse(file_iterator(file_path))
    response['Content-Type'] = 'application/octet-stream'
    response['Content-Disposition'] = 'attachment;filename="{f_name}"'.format(f_name=the_file_name)
    return response
回答
編輯回答
瘋子范

打開網(wǎng)頁檢查,如下圖

clipboard.png

發(fā)現(xiàn)是Content-Disposition出錯(cuò)

接下來,就針對(duì)這個(gè)屬性在網(wǎng)上搜集資料,解決步驟如下:

1、導(dǎo)入模塊

from django.utils.encoding import escape_uri_path

2、重寫該屬性

response['Content-Disposition'] = "attachment; filename*=utf-8''{}".format(escape_uri_path(the_file_name))

完整源碼

注:其中BUG1和BUG2普通解決方案不是最佳解決途徑

from django.http import StreamingHttpResponse

# 切片讀取文件
def file_iterator(filename,chunk_size=512):
    with open(filename,'rb') as f:
        while True:
            c=f.read(chunk_size)
            if c:
                yield c
            else:
                break

# 下載功能
def download_file(request):
    the_file_name = models.FileObj.objects.get(id=request.GET.get("id")).fileName  # 顯示在彈出對(duì)話框中的默認(rèn)的下載文件名
    print(the_file_name)
    file_path = os.path.join(file_dir,the_file_name) # 要下載的文件路徑
    response = StreamingHttpResponse(file_iterator(file_path))
    response['Content-Type'] = 'application/octet-stream' # #設(shè)定文件頭,這種設(shè)定可以讓任意文件都能正確下載,而且已知文本文件不是本地打開
    # response['Content-Disposition'] = 'attachment;filename="download.zip"' # BUG1:給出一個(gè)固定的文件名,且不能為中文,文件名寫死了
    # response['Content-Disposition'] = 'attachment;filename={0}'.format(the_file_name.encode("utf-8")) # BUG2:中文會(huì)亂碼
    response['Content-Disposition'] = "attachment; filename*=utf-8''{}".format(escape_uri_path(the_file_name)) # 正確寫法
    return response

正常下載zip文件的效果圖:
83f9f40699b429a21dbee5af2487788f.gif?_ga=2.176967205.1804310972.1529333628-377372411.1529333628

2017年7月6日 15:04