flask 如何处理和下载中文文件名的文件office excel word

在写 flask 后端的时候,特别是在做数据相关的操作的时候,产品往往需要我们做一个导出数据的需求,一般都是导出 excel 格式的文件。

那在 flask 上,如何实现请求连接即可让浏览器下载呢?有两种思路。

一:文件在本地磁盘,这时候我们只需要发送相应的地址过去即可。

二:通过 io 中的 BytesIO, 把文件以二进制的形式发送过去,这里我们需要使用 flask 自带的 send_file。

第一种的坏处在于不便于权限控制,拿到下载链接在哪都能下载,第二种方法的缺陷在于只能接收 get 请求,post 请求发送的文件浏览器是不能识别的。

要实现 send_file, 是很容易的, 代码如下(适用于 python 3):

import xlsxwriter
from io import BytesIO
from flask import Flask, send_file
 
app = Flask(__name__)
 
 
@app.route("/download", methods=["GET"])
def download():
    out = BytesIO()
    workbook = xlsxwriter.Workbook(out)
    table = workbook.add_worksheet()
    table.write(0, 0, "name")
    table.write(0, 1, "age")
    workbook.close()
    out.seek(0)
    return send_file(out, as_attachment=True, attachment_filename="dream.xlsx")
 
 
if __name__ == "__main__":
    app.run(debug=True)

这是一个完整的后端程序,能够直接跑起来。

其中我们用到了 xlsxwriter 这个库,用来生成一个 excel 文件, 直接传给 BytesIO() 成数据流的形式发出去,浏览器接收到这些数据流,回自动进行下载,文件名即是 send_file 参数中的 attachment_filename, 在我们这里便是 dream.xlsx 。

启动程序,在浏览器中输入 127.0.0.1:5000/download, 即可下载名为 dream.xlsx 的文件。

 

现在问题来了,这里的文件名是英文的,那我们需要中文怎么办?直接把 attachment_filename 参数改成 attachment_filename="测试表格.xlsx"可以么?

我们来试试:

return send_file(out, as_attachment=True, attachment_filename="测试表格.xlsx")

其余代码不变,仅有此处发成改变。

运行代码,浏览器访问下载试试。

浏览器没有任何反应,代表我们没有把数据流传给它,看程序,也报错了,报错信息:

UnicodeEncodeError: 'latin-1' codec can't encode characters in position 43-46: ordinal not in range(256)

编码问题。

解决办法如下:

import xlsxwriter
from io import BytesIO
from flask import Flask, send_file
from urllib.parse import quote
 
app = Flask(__name__)
 
 
@app.route("/download", methods=["GET"])
def download():
    out = BytesIO()
    workbook = xlsxwriter.Workbook(out)
    table = workbook.add_worksheet()
    table.write(0, 0, "name")
    table.write(0, 1, "age")
    workbook.close()
    out.seek(0)
    filename = quote("测试表格.xlsx")
    rv = send_file(out, as_attachment=True, attachment_filename=filename)
    rv.headers['Content-Disposition'] += "; filename*=utf-8''{}".format(filename)
    return rv
 
 
if __name__ == "__main__":
    app.run(debug=True)
 

我们从 urllib.parse 引入 quote, 首先对文件名进行编码,然后 send_file 中 作为 attachment_filename 的参数,这时候能成功下载文件,但是文件名是编码后的名字,要解码的话,我们需要在 headers 里面声明编码格式,即:

rv.headers['Content-Disposition'] += "; filename*=utf-8''{}".format(filename)

这样的话,对文件名进行 UTF-8 解码,我们的文件名就是中文了。

大功告成!

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值