原⽣JS实现后端⽂件流导出Excel(附Node后端代码)
原⽣JS实现后端⽂件流导出Excel(附Node后端代码)
导出⽂件⼀般是这两种⽅式:第⼀种是后端返回⼀个路径然后前端直接跳转下载。第⼆种也是本⽂使⽤的⽅式则是后端返回⽂件流,前端下载。第⼆种⼀般是ajax操作,所以还有可能后端返回的是json 格式的错误消息,这些都需要前端做相应的处理。
现在前端技术越来越成熟,这个操作完全可以直接⽤原⽣的js实现,这次直接抛开JQuery/axios等ajax库,来学习下原⽣js如何实现该操作。(学习原⽣js,虽然可能⽤不到。但是能加强你对现成的基于原⽣js封装的库的理解,所以是很有必要的)
下⽂将依次介绍:
后端效果
XMLHttpRequest实现⽂件下载
处理后端的返回结果
Fetch实现⽂件下载
当前时间的快捷键
Node.js后端导出代码
demo演⽰
注意:本⽂很多代码都⽤了ES6的新特性,有ES5需求的可以⽤babel转⼀下。
后端效果
先看看后端的效果是啥样的,我们再写前端代码。
先来看看模拟数据,⼀个很简单的⼈员列表,数据是这样的:
为了⽅便测试api我没有限制Request Method,所以我们可以直接在浏览器看效果。
根据名称搜索,没有数据时返回⼀个提⽰的json:
搜索名称中有'⼩'字的数据,可以下载Excel,excel中的数据是查询结果:
再看看后端的接⼝信息,中⽂部分被浏览器⾃动转码了:
看完后端的效果,咱们可以开始写前端代码。
XMLHttpRequest实现⽂件下载
先上代码:
//XMLHttpRequest实现⽂件下载
function exportExcelByXhr(name = '') {
var xhr = new XMLHttpRequest();
xhr.timeout = 3000;
网站模型图
xhr.open('GET', baseURL + name, true);
if (adyState == XMLHttpRequest.DONE && xhr.status == 200) {
//下载操作:⽂件流在sponse中
sponse);
}
}
xhr.send(null);//请求数据
}
流程也很简单,其实就是:
创建⼀个XMLHttpRequest -> 设置类型为blob -> 传⼊查询参数请求接⼝ -> 回调函数中处理响应结果
好像挺简单的,没啥好说的了。
handleBlob是我⾃⼰封装的js函数,对后端数据的处理(包括下载Excel,以及json的处理)在这个⾥⾯。处理后端的返回结果
想要处理后端的返回结果,我们得先知道sponse是个啥。先打印出来看看吧
console.sponse);
json的情况:
⽂件流的情况:
好家伙,既然已经知道了是啥玩意,我们就可以直接判断然后做相应的处理了。
只需要判断type是不是json,是json就转json,不是就转⽂件就⾏。
上代码:
//处理后端返回的Blob
function handleBlob(responseData) {
if (pe === "application/json") {
const reader = new FileReader();
const { msg } = JSON.sult);
alert(`后端消息:${msg}`);
}
} else {
// 如果后端响应头中没有指定 MIME Type , 就需要前端转⼀下
// const blob = new Blob([responseData], {
//    type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'
// });
openDownloadFile(responseData, '列表');
}
}
⽬前代码实现:如果是⽂件就下载,不是就弹出消息。
下载⽂件我专门搞了个openDownloadFile⽅法,⾥⾯没有ES6的语法,有需要的可以直接拿去⽤。Blob对象和url都可以导出。
/**
* 下载⽂件
* @param {any} urlObj 要下载的地址或者 Blob对象
* @param {any} saveName ⽂件保存的名字可选参数
*/
function openDownloadFile(urlObj, saveName) {
var openDownload = function (href, fileName) {
var downloadElement = ateElement('a');
downloadElement.target = "_blank";
downloadElement.href = href;
downloadElement.download = fileName || ""; // HTML5新增的属性,指定保存⽂件名,可以不要后缀
document.body.appendChild(downloadElement);
downloadElement.click(); // 点击下载
veChild(downloadElement); // 下载完成移除元素
}
if (typeof urlObj == 'object' && urlObj instanceof Blob) {
if (window.navigator && window.navigator.msSaveOrOpenBlob) {
//针对于IE浏览器的处理, 因部分IE浏览器不⽀持createObjectURL
window.navigator.msSaveOrOpenBlob(urlObj, saveName);
} else {
var url = ateObjectURL(urlObj); // 创建blob地址
openDownload(url, saveName);
vokeObjectURL(url); // 释放掉blob对象创建的地址
}
} else {
openDownload(urlObj, saveName);
}
}
Fetch实现⽂件下载
Fetch是2017年甚⾄更早出来的⼀个可以代替XMLHttpRequest做ajax请求的⽅式。虽然好像出来好⼏
年了,但是IE所有版本都是不⽀持的,其它浏览器在2017年之后发布的版本应该可以⽤。同时Fetch 不属于ECMAScript的范畴,它属于。
直接上代码,也挺简单的:
//Fetch实现⽂件下载
function exportExcelByFetch(name = '') {
fetch(baseURL + name, {
method: 'GET', // or 'PUT'
body: null, // data can be `string` or {object}!
headers: new Headers({
'responseType': 'blob'
})
})
.then(response => response.blob())
.then(data => {
handleBlob(data);
});
}
Node.js后端导出代码
搞了这么久前端咱们来看看后端怎么实现的吧。
css设置div滚动点样式
代码:
const Koa = require('koa');
const XLSX = require('xlsx');
const cors = require('koa2-cors');
const app = new Koa();
const titles = ['姓名', '年龄', '性别'];
const data = [
{ name: '陈⼩⽡', age: 18, sex: '男' },
{ name: '李飞', age: 33, sex: '男' },
{ name: '林妹妹', age: 22, sex: '⼥' },
{ name: '⼩明', age: 10, sex: '男' },plsql查看数据库地址
{ name: '⼩红', age: 9, sex: '男' },
{ name: '⼩军', age: 11, sex: '男' },
{ name: '⼩丽', age: 18, sex: '⼥' },
{ name: '甲', age: 45, sex: '男' },
{ name: '⼄', age: 21, sex: '男' },
{ name: '丁', age: 55, sex: '⼥' },
{ name: '武丑', age: 100, sex: '男' },
{ name: '⼦⽜', age: 101, sex: '男' },
{ name: '盐虎', age: 102, sex: '男' },
{ name: '峰⼉', age: 26, sex: '男' },
{ name: '坤鸡', age: 22, sex: '男' },
];
app.use(cors());
app.use((ctx, next) => {
if (ctx.path === '/') {
next();
return;
}
//不是根⽬录访问全部返回404创建文件的命令
ctx.status = 404;
});
app.use((ctx, next) => {
const name = ctx.query["name"];
//获取查询条件查询
const queryData = data.filter(p => p.name.includes(name));
let result, mimeType, filename;
if (queryData.length > 0) {
const xlsData = [titles];
for (const item of queryData) {
let d = [item.name, item.age, item.sex];
xlsData.push(d);
}
//json转excel
let sheet = XLSX.utils.aoa_to_sheet(xlsData);
//excel转node⽂件流
result = sheetToBuffer(sheet);
mimeType = 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet';
filename = `attachment;filename=${encodeURIComponent('⼈员列表')}.xlsx`;
} else {
result = { msg: '⽆数据可导出' };
mimeType = "application/json; charset=utf-8";
jquery下载文件请求
}
ctx.body = result;
ctx.set("Content-Type", mimeType);
if (filename) {
ctx.set("Content-Disposition", filename);
}
ctx.status = 200;
});
app.listen(3001);
/**
* 获取excel⽂件流
*/
function sheetToBuffer(sheet, sheetName) {
sheetName = sheetName || 'sheet1';
let workbook = {
SheetNames: [sheetName],
Sheets: {}
};
workbook.Sheets[sheetName] = sheet;
// ⽣成excel的配置项
let wopts = {
bookType: 'xlsx', // 要⽣成的⽂件类型
type: 'buffer'
};
let wbout = XLSX.write(workbook, wopts);
return wbout;
}
说下流程:
利⽤filter和includes筛选出符合条件的数据 -> 把excel表头和数据拼在⼀起 -> js数组对象转excel -> excel转流 -> 最后返回⽂件流并且设置响应头demo演⽰
放了个⽂本框和按钮,点击按钮可以导出:
本⽂全部源码都在这个demo⾥,可⾃⾏下载使⽤:

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。