一、上传文件
二、下载文件
本案例前端采用Vue2.0 后端Flask1.0.2,主要实现上传/下载文件功能
exportConfig(){
# 后端接口
exportConfig(this.ids).then(res => { # res为make_response()返回结果
if(res.status === 200){
const blob = new Blob([res.data],{type:"application/zip"}); #初始化Blob都西昂
const fileName = 'execute_file.zip'; # 文件名称
if ('download' in document.createElement('a')) { // 非IE下载
const elink = document.createElement('a')
elink.download = fileName
elink.style.display = 'none'
elink.href = URL.createObjectURL(blob)
document.body.appendChild(elink)
elink.click()
URL.revokeObjectURL(elink.href) // 释放URL 对象
document.body.removeChild(elink)
} else { // IE10+下载
navigator.msSaveBlob(blob, fileName)
}
this.$message({
message: "导出成功",
type: "success"
});
}else{
this.$message.error(res.data.data)
}
})
}
exportConfig(){
// 采用a标签的href指定的方式
const elink = document.createElement('a');
elink.download = 'execute_file.zip';
elink.style.display = 'none';
// elink.target = '_blank';
elink.href = config.baseUrl +'/接口路径/?ids='+ JSON.stringify(this.ids[0]);
document.body.appendChild(elink);
elink.click();
URL.revokeObjectURL(elink.href); // 释放URL 对象
document.body.removeChild(elink)
}
def services_export_file():
"""导出文件"""
obj = ConfigXxx()
res, err = obj.export()
if err:
return response.failed(data=err)
return res
class ConfigXxx:
def export(self):
"""导出"""
p_id = request.values.get('ids')
if not str(p_id).isdigit():
return None, f"不支持的导出参数【{p_id}】"
p_info, err = self.structure_config_data(p_id)
if err:
return None, err
file_handle = File()
# 生成文件
dirpath, err = file_handle.generate(p_info)
if err:
return None, err
export_data, err = file_handle.export_zip_file(dirpath)
if err:
return None, err
# 移除文件
file_handle.remove(dirpath)
# 核心->把生成的数据交给交给make_response处理
res = make_response(send_file(export_data, attachment_filename='execute_file.zip', as_attachment=True))
return res, None
class File:
def export_zip_file(self, dirpath):
"""查询导出文件"""
import os
import zipfile
from io import BytesIO
try:
memory_file = BytesIO()
with zipfile.ZipFile(memory_file, "w", zipfile.ZIP_DEFLATED) as zf:
dirname_list = list()
for path, dirnames, filenames in os.walk(dirpath):
dname = path.split('\\')[-1]
if not dirnames:
for filename in filenames:
zf.write(os.path.join(path, filename), os.path.join(*dirname_list, dname, filename))
else:
if dirname_list:
for filename in filenames:
zf.write(os.path.join(path, filename), os.path.join(*dirname_list, dname, filename))
else:
for filename in filenames:
zf.write(os.path.join(path, filename), os.path.join(dname, filename))
# 记录目录名称
dirname_list.append(dname)
# zf.setpassword("kk-123456".encode('utf-8'))
memory_file.seek(0)
return memory_file, None
except Exception as e:
return None, str(e)
1.前端用Blob实现导出失败,具体原因暂时不详,猜测flask.make_response()生成的文件的流Blob不支持,有知道原因的大神可以回复我一下!
2.原始a标签实现可以对接flask.make_response()下载文件
3.原始a标签实现下载有个隐藏的坑,上述实现方式在后端会有缓存,前端再次访问已经下载过的文件不会触发Services层,目前原因不祥,猜测是flask.make_response()内部注册session,缓存数据了,刨析源码中...
原文:https://www.cnblogs.com/zhangliang91/p/11912991.html