问题源起与一个静态文件下载的接口:python
from flask import Flask, current_app app = Flask(__name__) @app.route('/file_name') def file_download(file_name): return send_from_directory(current_app.root_path, file_name)
当file_name中有中文的时候出现内部错误提示:git
UnicodeEncodeError: 'latin-1' codec can't encode characters in position 46-47: ordinal not in range(256)
查找发现发现是中文编码出了问题,须要对响应头进行设置: 参考github
from flask import Flask, current_app,send_from_directory app = Flask(__name__) @app.route('/file_name') def file_download(file_name): res = make_response(send_from_directory(current_app.root_path, file_name, as_attachment=True, conditional=True)) res.headers["Content-Disposition"] = 'attachment; filename*="utf-8\'\'{}"'.format(file_name.encode().decode('latin-1')) return res
这下在本地运行终于能够正常下载了。但放到服务器上用gunicorn部署的时候又出现了问题:flask
Traceback (most recent call last): File "/home/dev/backend/backcode/convert-excel/venv/lib/python3.5/site-packages/gunicorn/workers/sync.py", line 135, in handle self.handle_request(listener, req, client, addr) File "/home/dev/backend/backcode/convert-excel/venv/lib/python3.5/site-packages/gunicorn/workers/sync.py", line 179, in handle_request resp.write_file(respiter) File "/home/dev/backend/backcode/convert-excel/venv/lib/python3.5/site-packages/gunicorn/http/wsgi.py", line 411, in write_file if not self.sendfile(respiter): File "/home/dev/backend/backcode/convert-excel/venv/lib/python3.5/site-packages/gunicorn/http/wsgi.py", line 390, in sendfile self.send_headers() File "/home/dev/backend/backcode/convert-excel/venv/lib/python3.5/site-packages/gunicorn/http/wsgi.py", line 337, in send_headers util.write(self.sock, util.to_bytestring(header_str, "ascii")) File "/home/dev/backend/backcode/convert-excel/venv/lib/python3.5/site-packages/gunicorn/util.py", line 509, in to_bytestring return value.encode(encoding) UnicodeEncodeError: 'ascii' codec can't encode characters in position 152-157: ordinal not in range(128)
通过一番查找,又找到了这个网址,参考里面的回答,又将代码改为下面这种形式:服务器
from urllib.parse import quote from flask import Flask, current_app,send_from_directory app = Flask(__name__) @app.route('/file_name') def file_download(file_name): res = make_response(send_from_directory(current_app.root_path, file_name, as_attachment=True, conditional=True)) res.headers["Content-Disposition"] = 'attachment; filename={}"'.format(quote(file_name)) return res
这下终于成功下载中文文件名的文件了。app