1 問題描述
Python的Flask項目,做上傳下載下傳時按照原檔案名進行,偶爾會出現中文檔案名,當執行下載下傳時在IE中會出現亂碼問題。quote是将檔案名urlencode化,然後以适應IE浏覽器
2 解決方案
import os
from urllib.parse import quote
# from urllib import quote for python2
from flask import request, make_response, send_from_directory
@app.route('/download', methods=["POST"])
def download():
"""檔案下載下傳"""
# 擷取參數
data_dict = dict(request.form)
file_name = data_dict["filename"]
# 擷取檔案路徑
file_path = os.path.join(os.getcwd())
if os.path.exists(file_path): # 如果存在檔案
rsp = make_response(send_from_directory(file_path, file_name, as_attachment=True))
utf_filename = quote(file_name.encode('utf-8'))
rsp.headers["Content-Disposition"] = "attachment;filename*=UTF-8''{}".format(utf_filename)
rsp.headers['Content-Type'] = "application/octet-stream; charset=UTF-8"
return rsp
代碼說明:
Content-Disposition中的filename進行了兩次URL轉碼。以漢字“帥”為例:
前端下載下傳時:
- 第一次轉碼,“帥” 變為 “%E5%B8%85”。
- 第二次轉碼,“%E5%B8%85” 變為 “%25E5%25B8%2585”(第二次轉碼時,因為%是特殊字元,是以會轉為%25)。
- Chrome浏覽器可以自動執行兩次URL解碼,是以下載下傳的檔案名是正常的。
- IE浏覽器隻執行一次URL解碼,是以下載下傳的檔案名是第一次編碼的結果(%E6%BC%AB)
解決方案是在傳回給前端前對Content-Disposition中的filename先進行一次URL解碼(實際我是對filename這個參數進行了解碼,因為檔案伺服器是用的第三方的)。
此外,當檔案名為中文(未執行URL編碼)字元串時,IE下載下傳也為亂碼,因為IE對中文字元串又執行了一次URL解碼。解決方案是将中文字元串進行URL編碼。
是以,總結下來,關鍵的問題就在于IE浏覽器對filename隻進行一次解碼,而chrome對這種情況是進行了優化的