问题描述:
做了一个小功能,前端vue点击下载按钮,flask后端返回一个csv文件流(由于项目需要,encoding为gb2312),但是浏览器下载之后发现编码为utf8。
前端代码
downloadTradeList(){
downloadPositionTradeList({ id: this.$route.query.id }).then(res=>{
const content = res;
console.log(res);
const blob = new Blob([content])
console.log(blob);
const fileName = 'tradelist.csv'
if ('download' in document.createElement('a')) { // 非IE下载
const elink = document.createElement('a')
elink.download = fileName
elink.style.display = 'none'
elink.href = URL.createObjectURL(blob)
document.body.appendChild(elink)
elink.click()
URL.revokeObjectURL(elink.href) // 释放URL 对象
document.body.removeChild(elink)
} else { // IE10+下载
navigator.msSaveBlob(blob, fileName)
}
});
},
后端代码
df = pd.DataFrame(data=orders,columns=columns)
csv_bin_data = df.to_csv(index=False,encoding='gb2312')# (index=True, encoding="utf-8")
response = Response(
csv_bin_data,
status=200,
headers=common_util.generate_download_headers("csv"),
#mimetype="application/csv",
mimetype="text/csv",
)
print(type(response.headers),response.headers)
return response
打印信息
werkzeug.datastructures.Headers
Content-Disposition: attachment; filename=20210928_120943.csv
Content-Type: text/csv; charset=utf-8
Content-Length: 1270
问题分析
由打印信息 可将问题定位在后端,虽然csv_bin_data是以gb2312编码,但是header里仍然是utf8。 查看flask的Response源码
原来flask使用的werkzeug.datastructures.Headers类默认编码utf8,并且没有暴露接口供修改。
解决方案
class MyResponse(Response):
charset = "gb2312"
很简单 将需要其他编码返回的Response用MyResponse代替,问题解决。