vue二进制流文件导出excel
甜仔是只猫 人气:0vue二进制流文件导出excel
问了一下其他的后端,他们公司前端是a标签,后端是给了一个地址,a标签或者window.open()都可以实现。
我们公司是后端返回的二进制流文件,实现了一下,亲测可以,没有问题
前端代码
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> </head> <body> <button id="btn">下载</button> <!-- yarn add axios --> <script src="node_modules/axios/dist/axios.min.js"></script> <script> const btn = document.getElementById("btn"); btn.onclick = function () { axios({ method: "post", url: "http://localhost:3000/download", data: { // test: "test data", }, responseType: 'blob' //返回类型 }).then((res) => { let name = '合格率' //注意这里不可以再加.xlsx了,函数中已经封装了 createExcel(res.data, name) //这里就直接这样调用方法就行了 }); } // vue中可以写方法 然后再暴露出去 function createExcel(res, name) { let blob = new Blob([res], { type: 'application/vnd.ms-excel' }) let fileName = name + '.xlsx' // 允许用户在客户端上保存文件 if (window.navigator.msSaveOrOpenBlob) { navigator.msSaveBlob(blob, fileName) } else { var link = document.createElement('a') link.href = window.URL.createObjectURL(blob) link.download = fileName link.click() //释放内存 window.URL.revokeObjectURL(link.href) } } // 1.msSaveBlob:只提供一个保存按钮 //window.navigator.msSaveBlob(blobObject, 'msSaveBlob_testFile.txt'); // 2.msSaveOrOpenBlob:提供保存和打开按钮 // window.navigator.msSaveOrOpenBlob(blobObject, 'msSaveBlobOrOpenBlob_testFile.txt'); </script> </html>
后端node
const http = require("http"); const fs = require("fs"); const server = http.createServer((req, res) => { if (req.url === "/download") { res.writeHead(200, { "Content-type": "application/vnd.ms-excel", // 返回 excel // 跨域设置 "Access-Control-Allow-Origin": "*", "Access-Control-Allow-Headers": "content-type", }); // 异步读取文件内容 这里新建了一个test.xlsx的excel fs.readFile("test.xlsx", (err, data) => { // 返回二进制文件流 res.end(data); }); } }); server.listen(3000, () => { console.log("好厉害,3000的服务器起来了"); });
关于二进制文件流导出Excel文件的一些坑
实现下载效果
<el-button type="warning" icon="el-icon-download" size="mini" @click="download()">导出</el-button>
//下载操作 download() { return axios({ url: '/download/sms', method: 'post', data: this.queryForm, responseType: 'blob', headers: { 'Content-Type': 'application/json' } }) .then(res => { console.log(res, '返回数据列'); const blob = new Blob([res.data], { type: 'application/vnd.ms-excel' }); console.log(blob, '----------0990'); const fileName = '短信列表.xls'; const linkNode = document.createElement('a'); linkNode.download = fileName; //a标签的download属性规定下载文件的名称 linkNode.style.display = 'none'; linkNode.href = URL.createObjectURL(blob); //生成一个Blob URL document.body.appendChild(linkNode); linkNode.click(); //模拟在按钮上的一次鼠标单击 URL.revokeObjectURL(linkNode.href); // 释放URL 对象 document.body.removeChild(linkNode); }) .catch((err) => { console.log(err); }); return res; },
踩坑
1、刚开始看网上说需要axios原生才能请求,然后就引入了axios之后但是一直报错,导致download的then代码无法执行,直接走catch,输出错误
研究了半天才发现是blob返回没有code,也没有message,而我在拦截器中直接设置了code的判断拦截,所以导致请求一直报错
2、在发送请求时必须要加上responseType: ‘blob’,不然导出的文件是乱码格式的
3、在then里面定义的blob new出来的数据需要再走一层,而不是直接输出
以上为个人经验,希望能给大家一个参考,也希望大家多多支持。
加载全部内容