天天看點

Flask下載下傳檔案,中文檔案名在IE浏覽器下出現亂碼

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對這種情況是進行了優化的