摘要:解决办法如下测试表格我们从引入,首先对文件名进行编码,然后中作为的参数,这时候能成功下载文件,但是文件名是编码后的名字,要解码的话,我们需要在里面声明编码格式,即这样的话,对文件名进行解码,我们的文件名就是中文了。
在写 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 的文件。
我们打开看看:
的确是我们生成的一个 excel 表格。
现在问题来了,这里的文件名是英文的,那我们需要中文怎么办?直接把 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 解码,我们的文件名就是中文了。
如图:
打开文件,也是我们想要的,如图:
大功告成!
当然实际生产工作中,数据量是是非常大的,生成 excel 文件将会特别耗时,我们当然不希望我们的程序在此堵塞, 这时候我们可以使用 celery 异步任务,返回前端一个任务 ID, 前端去轮询这个任务 ID,当文件生成好了,即可开始下载。
由于有些时候我们 get 请求无法满足我们的参数传递,比如有多个嵌套对象作为参数传递,我们必须使用 post 请求,这时候同样可以采用 celery 异步任务的方式,返回任务 ID, 轮询任务状态,下载文件。
之后我会写一篇教程,celery 异步任务。
文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。
转载请注明本文地址:https://www.ucloud.cn/yun/41093.html
摘要:最近由于工作关系,开始写程序,同事有用的,有用的。第一种适合及以上版本,因为在版本起,出现了文件,配置可以写成用文件启动程序,实测可以触发断点。 最近由于工作关系,开始写flask web程序,同事有用Vim的,有用PyCharm的。在调研了一通python的编辑器,IDE之后,发现Visual Studio Code相对比较适合我。 VSC有相对较全的功能,比较好看舒服的主题,良好的...
摘要:原创个人网站欢迎访问说明后台用的的框架,后台对你理解这篇文章没什么影响,你可以使用作为上传区引入和然后使用表单定义一个即可完成第一种上传第一种上传效果作为上传区作为上传区也很简单点我上传下面两行是和的方式实现绑定的例子 原创【个人网站欢迎访问】说明:后台用的python的flask框架,后台对你理解这篇文章没什么影响,你可以使用php form作为上传区 引入Dropzone.js和d...
摘要:原创个人网站欢迎访问说明后台用的的框架,后台对你理解这篇文章没什么影响,你可以使用作为上传区引入和然后使用表单定义一个即可完成第一种上传第一种上传效果作为上传区作为上传区也很简单点我上传下面两行是和的方式实现绑定的例子 原创【个人网站欢迎访问】说明:后台用的python的flask框架,后台对你理解这篇文章没什么影响,你可以使用php form作为上传区 引入Dropzone.js和d...
摘要:原创个人网站欢迎访问说明后台用的的框架,后台对你理解这篇文章没什么影响,你可以使用作为上传区引入和然后使用表单定义一个即可完成第一种上传第一种上传效果作为上传区作为上传区也很简单点我上传下面两行是和的方式实现绑定的例子 原创【个人网站欢迎访问】说明:后台用的python的flask框架,后台对你理解这篇文章没什么影响,你可以使用php form作为上传区 引入Dropzone.js和d...
摘要:链接中文翻译常用库推荐除了上面提到的之外,也是一个很好的选项。官网中文翻译如果你要编写简单的爬虫,来爬去互联网上的信息,或者调用一些外部的机遇的接口,使用这个库再也合适不过了。 作者:安龙 LeanCloud 工程师 引言 :前段时间有同学反映 Python 的学习资源汇总很少。那么学习资料哪个质量更好,效率更高?Python 有哪些非常值得学习的库?2017 年了学 2 还是学 3 ...
阅读 1660·2019-08-30 15:54
阅读 3293·2019-08-26 17:15
阅读 3495·2019-08-26 13:49
阅读 2564·2019-08-26 13:38
阅读 2270·2019-08-26 12:08
阅读 2989·2019-08-26 10:41
阅读 1353·2019-08-26 10:24
阅读 3355·2019-08-23 18:35