如何更改烧瓶中的下载名称?

时间:2017-01-09 08:37:41

标签: python flask

我有一个小项目,必须回复一些文件。我知道使用nginx将是更好的决定,但文件非常小。

我的计划的一部分:

return send_file(os.path.join(filepath, filename))

该行返回文件名为download的文件,没有任何格式或类似内容。已下载的文件名始终相同,不依赖于文件的真实名称。文件的真实姓名为table.csv。如何以正确的文件名返回文件?

4 个答案:

答案 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_attachmentattachment_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

然后,在客户端下载代码中,您可以检查响应标头以从相同的自定义标头获取文件名:

screenshot of header

# 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)