背景:我们在进行后台相关的页面开发过程,常常会涉及到数据量较大的相关开发,比如将浏览的页面数据导出到excell中浏览或操作。这时候常常会有下面两种情况:
一. 页面数据分页展示
此时可以通过服务器直接返回xlsx文件的url,然后通过创建超链标签元素a,然后利用a.href=url直接在浏览器下载文件
//关键实现函数代码
const exportCsv=(url)=>{
let a=document.creatElement('a') //创建标签a
a.href=url //将服务器返回的文件url赋值给a
a.download=url.split('/').pop() //下载文件
a.click()
}
二. 页面一次展示所有数据
此时服务器不会返回url,需要前端结合Node库和中间件实现对数据的处理和写入csv文件中,从而提供下载,主要利用nodejs组件库exceljs
前端代码:
//下载csv文件
const downloadCsv = () => {
//headKeys为列表每列写入的内容
const headKeys = getBaseTableColumnsOption().map((item:any) => item.prop); //getBaseTableColumnsOption为表格的表头内容
//headNames为表头的内容
const headNames = getBaseTableColumnsOption().map((item:any) => item.label);
exportCsv(headKeys, headNames,tableData, 'test.csv'); //tableData为需要写入csv的数据
};
Node代码
import * as ExcelJS from 'exceljs';
export const exportCsv = async (headKeys: string[], headNames:string[], tableData: any[], filename: string) => {
const workbook = new ExcelJS.Workbook();
const worksheet = workbook.addWorksheet('sheet1', {
properties: { tabColor: { argb: 'FFC0000' } }
});
const columns = headKeys.map((item: string) => ({ name: item, style: {} }));
const columnsName = headNames.map((item: string) => ({ name: item, style: {} }));
const rows = tableData.map((item) => {
const row: any[] = [];
const columnKeys = columns.map((item) => item.name);
columnKeys.forEach((prop: string) => {
row.push(item[prop]);
});
return row;
});
worksheet.addTable({
name: 'MyTable',
ref: 'A1',
headerRow: true,
// totalsRow: true,
style: {
theme: 'TableStyleLight',
showRowStripes: true
},
columns: columnsName,
rows: rows
});
const buffer = await workbook.csv.writeBuffer(); //对需要写入的数据进行转换
// const blob = new Blob([buffer], { type: 'text/csv' });
// const blob = new Blob([buffer], { type: 'text/csv' }); //blob对象前添加unicode标识符可以解决乱码问题
const blob = new Blob(['\ufeff' + buffer], { type: 'text/csv, charset = UTF - 8' }); //注意unicode'\ufeff'不能缺少,缺少会产生中文乱码现象
const a = document.createElement('a');
a.download = filename
const url = URL.createObjectURL(blob);
a.href = url;
document.body.appendChild(a);
a.click();
URL.revokeObjectURL(url);
document.body.removeChild(a);
};