我有一个小项目,必须回复一些文件。我知道使用nginx
将是更好的决定,但文件非常小。
我的计划的一部分:
return send_file(os.path.join(filepath, filename))
该行返回文件名为download
的文件,没有任何格式或类似内容。已下载的文件名始终相同,不依赖于文件的真实名称。文件的真实姓名为table.csv
。如何以正确的文件名返回文件?
答案 0 :(得分:20)
您需要为浏览器设置Content-Disposition: attachment; filename=....
HTTP标头以使用正确的文件名。
您可以通过设置send_file()
参数让as_attachment=True
为您设置此标头。然后从您传入的文件对象中获取文件名。使用attachment_filename
参数显式设置不同的文件名:
return send_file(os.path.join(filepath, filename), as_attachment=True)
来自flask.send_file
documentation:
as_attachment
- 如果您要使用True
标头发送此文件,请设置为Content-Disposition: attachment
。attachment_filename
- 附件的文件名,如果它与文件的文件名不同。
您可能希望改用flask.send_from_directory()
function。该函数首先确保文件名存在(如果不存在则引发NotFound
),并确保文件名不包含可能用于“转义”目录的任何..
相对元素。将此用于从不受信任来源获取的所有文件名:
return send_from_directory(filepath, filename, as_attachment=True)
答案 1 :(得分:3)
在我的情况下,设置as_attachment
和attachment_filename
无效,因为Content-Disposition: attachment
没有出现在响应的客户端副本中。
如果启用了Flask-CORS,则可以将expose_headers
设置为用于指定文件名的自定义标头(例如“ x-suggested-filename ”)进行初始化。 。然后将该标头添加到响应中。
# In file where the Flask app instance is initialized
app = Flask(__name__)
CORS(app, expose_headers=["x-suggested-filename"])
# In file with the download endpoint
result = send_file("/full/path/to/some/file",
mimetype="text/plain", # use appropriate type based on file
as_attachment=True,
conditional=False)
result.headers["x-suggested-filename"] = "use_this_filename.txt"
return result
然后,在客户端下载代码中,您可以检查响应标头以从相同的自定义标头获取文件名:
# Using axios and FileSaver
let response = await axios.get(downloadUrl, downloadConfig);
let filename = response.headers["x-suggested-filename"];
FileSaver.saveAs(response.data, filename);
答案 2 :(得分:1)
在某些情况下,文件名仍然不可见。要确保拥有它,您应该设置“ x-filename”标头并公开此标头。
function b64EncodeUnicode(str) {
return btoa(encodeURIComponent(str).replace(/%([0-9A-F]{2})/g, function(match, p1)
{
return String.fromCharCode(parseInt(p1, 16))
}))
}
function b64DecodeUnicode(str) {
return decodeURIComponent(Array.prototype.map.call(atob(str), function(c) {
return '%' + ('00' + c.charCodeAt(0).toString(16)).slice(-2)
}).join(''))
}
console.log(b64DecodeUnicode(b64EncodeUnicode('✓ à la\nmo\nde')));
答案 3 :(得分:1)
我以前遇到过这个问题,我尝试了这里提到的许多解决方案,最后我可以通过编写文件的正确的模仿类型来解决此问题
这是我的示例:
@app.route('/download_report')
def download_summary():
return send_file('Report.csv', mimetype='application/x-csv', attachment_filename='summary_report.csv', as_attachment=True)