Flask[邂逅]
flask 下载文件
flask提供了两个可进行下载的函数:send_from_directory 和 send_file
send_from_directory
send_from_directory函数内部调用了send_file,可以认为,真正执行下载操作的其实是send_file,那么send_from_directory存在的意义是什么呢?
1 | def send_from_directory(directory, filename, **options): |
上面为send_from_directory函数的全部代码,在调用send_file函数之前,它做的最重要的事情就是获得一个安全的filename。
下载文件的名字,为用户发请求时传给后端的,如果直接使用客户端发送的文件名字,则存在安全隐患。
关于这个安全隐患,其本质都是利用地址拼接这个动作修改实际操作文件的地址,为了防止黑客恶意下载,函数第一行代码便是使用safe_join函数,防止黑客通过修改filename的值达到下载关键文件的目的。
因此,实际生产环境下,推荐使用send_from_directory函数
send_file
使用send_file例子
1 | from flask import send_from_directory, send_file |
send_file函数会调用guess_type函数获取文件的类型,设置响应头里的content-type。
在浏览器里打开 http://127.0.0.1:5000/download 这个url,会直接进行下载,但下载的文件名字并不是所期望的3.xlsx,浏览器在保存时用的名字是download.xlsx。
如果希望浏览器下载保存文件时使用的名字是3.xlsx,则需要将参数as_attachment设置为True。
秘密藏在响应头的首部中,由于设置了as_attachment为True,flask会添加Content-Disposition
1 | Content-Disposition: attachment; filename=3.xlsx |
这样,浏览器便明白文件名是什么。
如果希望浏览器以其他的名字保存该文件,则可以单独设置attachment_filename 参数
1 |
|
这样,浏览器就会使用test.xlsx来保存文件。
处理下载文件中出现中文的乱码问题
当attachment_filename参数设置为中文文件名时,flask会报错误
1 | UnicodeEncodeError: 'latin-1' codec can't encode characters in position 43-44: ordinal not in range(256) |
引发这个问题的原因,可以一直追溯到http协议,按照协议规定,HTTP Header 中的文本数据必须是 ASCII 编码的,为了解决header出现其他编码的问题,浏览器各显神通,这里的原理与历史可以参考这篇文章 https://blog.csdn.net/u011090495/article/details/18815777
我这里直接给出解决办法 COOLPYTHON NB
1 |
|