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