RFC 2231 section 4描述如何指定的編碼來代替Latin-1的的用於一個標頭值。使用標頭選項filename*=UTF-8''...
,其中...
是網址編碼的名稱。您還可以包含filename
選項以提供拉丁-1回退。
直到最近,瀏覽器並沒有一貫支持這一點。 This page有一些關於瀏覽器支持的指標。值得注意的是,IE8將忽略UTF-8選項,並且如果UTF-8選項位於Latin-1選項之前,將會完全失敗。
燒瓶0.13(尚未發佈)將support calling send_file
with Unicode filenames。一旦發佈,您可以使用send_file
和as_attachment=True
以及Unicode文件名。
from flask import send_file
@app.route('/send-python-report')
def send_python_report():
return send_file('python_report.html', as_attachment=True)
在此之前,您可以使用Flask將使用的相同過程手動構建標頭。
import unicodedata
from flask import send_file
from werkzeug.urls import url_quote
@app.route('/send-python-report')
def send_python_report():
filename = 'python_report.html'
rv = send_file(filename)
try:
filename = filename.encode('latin-1')
except UnicodeEncodeError:
filenames = {
'filename': unicodedata.normalize('NFKD', filename).encode('latin-1', 'ignore'),
'filename*': "UTF-8''{}".format(url_quote(filename)),
}
else:
filenames = {'filename': filename}
rv.headers.set('Content-Disposition', 'attachment', **filenames)
return rv
對於代替如果文件名由用戶輸入提供的,你應該使用send_from_directory
安全。該過程與上述相同,代替該功能。
WSGI並不能確保的頭選項的順序,所以如果你想支持IE8必須構造完全採用dump_options_header
與OrderedDict
手動標頭值。否則,filename*
可能出現在filename
之前,如上所述,在IE8中不起作用。
from collections import OrderedDict
import unicodedata
from flask import send_file
from werkzeug.http import dump_options_header
from werkzeug.urls import url_quote
@app.route('/send-python-report')
def send_python_report():
filename = 'python_report.html'
rv = send_file(filename)
filenames = OrderedDict()
try:
filename = filename.encode('latin-1')
except UnicodeEncodeError:
filenames['filename'] = unicodedata.normalize('NFKD', filename).encode('latin-1', 'ignore')
filenames['filename*']: "UTF-8''{}".format(url_quote(filename))
else:
filenames['filename'] = filename
rv.headers.set('Content-Disposition', dump_options_header('attachment', filenames))
return rv
將該溶液現在產生在Chrome 61 – LotusH
一個ERR_RESPONSE_HEADERS_MULTIPLE_CONTENT_DISPOSITION @LotusH離開了Latin-1的名稱,然後。如果你想報告給Flask,那會很有幫助。 – davidism