Flask返回中文名文件的文件流對象無響應
使用Flask的Response返回文件流對象的時候遇到這樣的問題,返回英文名文件時一切正常,當返回中文名稱的文件時瀏覽器正常,網絡請求也返回200的響應但卻沒有下載文件,抓包發現返回的響應頭里並沒有Content-Type和Content-Disposition字段,分析可能是這個原因。經過搜索發現也有人遇到過這個問題,最終通過urllib模塊里方法編碼文件名稱后能夠正常返回。
from urllib.parse import quote
...
file_name = "測試.xlsx"
response.headers['Content-Type'] = 'application/octet-stream'
response.headers['Content-Disposition'] = 'attachment;filename*=utf-8"{0}"'.format(quote(file_name))
return response
當以上代碼運行一段時間發現firefox瀏覽器下載文件會變成utf-8測試.xlsx_這樣的文件名稱,又經過一番搜索和嘗試,最后發現直接將文件名編碼為latin-1和iso-8859-1這兩個編碼能夠所有瀏覽器都能顯示正常,如下:
file_name = "測試.xlsx"
response.headers['Content-Type'] = 'application/octet-stream'
response.headers['Content-Disposition'] = 'attachment;filename="{0}"'.format(file_name.encode("latin-1"))
# response.headers['Content-Disposition'] = 'attachment;filename="{0}"'.format(file_name.encode("iso-8859-1"))
return response
當我把代碼再次更新並以gunicorn啟動后發現下載文件直接500了,我靠,百思不得其解,難不成gunicorn做了啥額外的配置或者操作?仔細想想gunicorn部署后socket通信應該加了些操作吧(但不知道是具體哪里問題),分析了gunicorn的配置和運行原理沒發現通過修改gunicorn設置的解決辦法。然而最后陰差陽錯的解決了,代碼如下:
from urllib.parse import quote
...
file_name = "測試.xlsx"
response.headers['Content-Type'] = 'application/octet-stream'
response.headers['Content-Disposition'] = 'attachment;filename={0};filename*={0}'.format(
quote(file_name))
return response
講道理這里我都不知道為什么這樣能夠解決,記錄下,以后詳細研究。
參考:
https://blog.csdn.net/liuyaqi1993/article/details/78275396
https://segmentfault.com/a/1190000012514419
