遇到了个问题,后端直接返回表格的 Stream,在 ApiFox 里点下载出来的表格文件完全正常,但是在前端里导出的内容不行,会报错:Excel 无法打开文件“XXXX.xlsx”,因为文件格式或文件扩展名无效。请确定文件未损坏,并且文件扩展名与文件的格式匹配。
前端是这么写的:
axios.post(BASE_URL + "/output", JSON.stringify(realMultiFileResponseTypeList), {
headers: {
"Content-Type": "application/json"
},
responseType: 'blob'
}).then(function(response) {
const {data, headers} = response
const regex = /filename="(.*?)"/gm
const fileName = regex.exec(headers['content-disposition']) ![1]
console.log(fileName)
const _utf = '\uFEFF';
const blob = new Blob([data], {
type: "application/octet-stream"
});
let url = URL.createObjectURL(blob);
let dom = document.createElement('a')
dom.href = url
console.log(url)
dom.download = fileName
dom.style.display = 'none'
document.body.appendChild(dom)
dom.click()
URL.revokeObjectURL(url)
document.body.removeChild(dom)
}).
catch(function(error) {
console.log(error);
});
这个也是很常见的导出,基本搜一搜 JavaScript 导出二进制 都是类似的内容,但是 XLSX 不适用。因为 XLSX 不同于 XLX 是个文件,它本质上是一个压缩文件,前端单纯地 URL.createObjectURL
没有办法实际生成 XLSX,所以需要 SheetJS
这个库。
SheetJS:https://docs.sheetjs.com/
安装就不赘述了,直接贴一下结果的代码:
import * as XLSX from 'xlsx';
...
axios.post(BASE_URL + "/output", JSON.stringify(realMultiFileResponseTypeList), {
headers: {
"Content-Type": "application/json"
},
responseType: 'blob'
}).then(async function(response) {
const {data, headers} = response
const regex = /filename="(.*?)"/gm
const fileName = regex.exec(headers['content-disposition']) ![1] console.log(fileName)
const _utf = '\uFEFF';
const blob = new Blob([data], {
type: "application/octet-stream"
});
const wb = XLSX.read(await blob.arrayBuffer(), {type: "array"});
XLSX.writeFile(wb, fileName);
}).
catch(function(error) {
console.log(error);
});
主要变化其实就是创建一个 Workbook
,把 blob
的东西转成 ArrayBuffer 后塞给它,然后调用 XLSX.writeFile()
就行。这里就不需要再手动创建一个隐藏的 a
标签模拟点击再删除了,writeFile()
里本身写好了,调用就行(
另外,因为其中出现了 await
,axios 的 then 需要带有 async
。
共有 0 条评论