后端数据转为Blob 前端将Blob转为excel文件
1. 数据获取
后端获取对应血压数据 后端将列表数据转变为数据流
- 规定表头设置响应体
//数据表格
let data = [];
//非管理员用户只导出自己的血压
if(userAdmin === false){
data[0] = ['日期','时间段','高压','低压','心跳','备注'];
}else{//管理员表头不同
data[0] = ['用户','日期','时间段','高压','低压','心跳','备注'];
}
- 按表头顺序写入数组
//导出列表 按表头添加到列表
list.forEach((element) =>{
let arrInner = [];
if(userAdmin === true){
arrInner.push(element.userAccount);
}
arrInner.push(formatTimestamp(element.recordDate));
arrInner.push(bpNumberToTag(element.timeTag));
arrInner.push(element.sys);
arrInner.push(element.dia);
arrInner.push(element.pul);
arrInner.push(element.note);
data.push(arrInner);
});
- 后端
- 工具类将文件转为Buffer
//导出excel 文件名格式 用户名数据类当前时间
const toExcelFile = (fileName,data) =>{
//后端生成excel成功
const buffer = xlsx.build([{name: fileName, data: data}]); //生成数据流
return buffer;
}
2.后端路由处理 返回的body必须只有文件的数据流否则会损坏
/*
响应体设置
*/
// request.headers['content-disposition'] = `attachment; filename=${fileName}`; //设置文件名
//前端允许Content-Disposition
ctx.set("Access-Control-Expose-Headers", "Content-Disposition");
//设置文件名
ctx.attachment(Buffer.from(fileName).toString('base64'));
ctx.body = toExcelFile(fileName ,data); //buffer文件流
2.数据导出
前端将数据流arraybuffer转为结合a标签进行下载。由于涉及到响应头而且不能用自己封装result方法,就重新封装了一个下载文件的函数
export const downloadExcel = (url,data) =>{
//请求数据流
return axios.post(getURL(url) , data , {
headers : getHeaders(),
responseType: 'arraybuffer',
}).then((res)=>{
//处理数据流并下载
// console.log(res);
//arraybuffer 转为Blob
let blob = new Blob([res.data],{type:'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'});
//文件名获取它的类型是buffer(为了传输中文)
const fileName = res.headers['content-disposition'].split(';')[1].split('filename=')[1]
//a标签模拟点击
const link = document.createElement('a');
link.style.display = 'none';
link.href = URL.createObjectURL(blob);//创建url对象
link.download = Buffer.from(fileName,'base64').toString(); //文件名buffer转string
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
URL.revokeObjectURL(link.href);//销毁url对象
});
};
参考连接