安装依赖:
pnpm install xlsx --save
代码1:
import * as XLSX from 'xlsx';
/**
* 读取文件并输出为数组
* @param url 请求地址
*/
export const readFileAndGetArray = (url: string) => {
let result = [] as any;
fetch(url)
.then((res) => res.blob())
.then((blob) => {
const reader = new FileReader();
console.log(120, blob);
//以二进制方式读取文件
reader.readAsBinaryString(blob); // readAsBinaryString传参为blob格式
reader.onload = (e) => {
//获取文件数据
const data = e.target?.result; //e.target.value
//XLSX读取文件
const wb = XLSX.read(data, { type: 'binary' });
console.log(129, wb);
//获取第一张表
const wsname = wb.SheetNames[0];
const ws = wb.Sheets[wsname];
const sheetRowList = XLSX.utils.sheet_to_json(ws, { header: 1 }).filter((itemArr: any) => itemArr.length); // 表格行内容数组,去除空内容的行
console.log(137, wsname, ws, sheetRowList);
const sheetHeadArr = sheetRowList[0] as string[]; // 表头字符串数组
// 将属性名数组和数据数组转换为对象数组
const arr = sheetRowList.slice(1).map((rowArr: any) => {
const obj = {} as any;
sheetHeadArr.forEach((key: string, index: any) => {
obj[key] = rowArr[index];
});
return obj;
});
console.log(149, sheetHeadArr, sheetRowList.slice(1), arr);
result = arr;
};
});
return result;
};
上面是请求本地文件的情况。若是调后台接口获取文件,则获取到返回值文件流data后,再
let blob = new Blob([data], { type: 'application/vnd.ms-excel' });
其中type为下载的文件的对应格式。文档
之后再 reader.readAsBinaryString(blob); 就可以了。
但是遇到问题
.then 和 reader.onload都是异步任务,readFileAndGetArray的return result是同步任务,返回的最终result是初始值。
改造代码2:
import * as XLSX from 'xlsx';
/**
* 读取文件并输出为数组
* @param url 请求地址
*/
export const readFileAndGetArray = async (url: string) => {
const res = await fetch(url);
const blob = await res.blob();
// 用new Promise 的resolve来异步返回最终结果
return new Promise<any[]>((resolve) => {
const reader = new FileReader();
//以二进制方式读取文件
reader.readAsBinaryString(blob); // readAsBinaryString传参为blob格式
reader.onload = (e) => {
//获取文件数据
const data = e.target?.result; //e.target.value
//XLSX读取文件
const wb = XLSX.read(data, { type: 'binary' });
//获取第一张表
const wsname = wb.SheetNames[0];
const ws = wb.Sheets[wsname];
const sheetRowList = XLSX.utils.sheet_to_json(ws, { header: 1 }).filter((itemArr: any) => itemArr.length); // 表格行内容数组,去除空内容的行
const sheetHeadArr = sheetRowList[0] as string[]; // 表头字符串数组
// 将属性名数组和数据数组转换为对象数组
const arr = sheetRowList.slice(1).map((rowArr: any) => {
const obj = {} as any;
sheetHeadArr.forEach((key: string, index: any) => {
obj[key] = rowArr[index];
});
return obj;
});
resolve(arr);
};
});
};
把两个.then 用await代替,reader.onload不能用await ,所以用new Promise 的resolve来异步返回最终结果。文档