记录下csv文件分片处理下载的流程和内容
目录
2. 分片处理,循环存入数组,转blob,filesaver存入
1.安装mock.js和file-saver,并引入
下载依赖:
cnpm install mockjs -S
cnpm install file-saver -S
引入依赖
import Mock from 'mockjs'
import FileSaver from 'file-saver'
2. 分片处理,循环存入数组,转blob,filesaver存入
重要的地方在于:
异步处理,不阻塞主线程
分片处理,不会一次性传输数据过大,造成页面卡顿甚至崩溃
async exportCsv(total, size) {
try {
if (!total) throw "无数据";
// 分片
const step = Math.ceil(total / size);
// CSV 缓存
let csvArray = [];
// 表头处理 - 一般表头由外部传入
csvArray.push(['编号', '用户名', '官网', '报价', '创建日期'].join() + '\n');
// 通用分片
for (let i = 0; i < step; i++) {
await new Promise((resolve, reject) => {
(async () => {
try {
// 创建指定个数的随机数据
const data = this.csvdata.slice(i, i + size);
// 格式化为 CSV 字符串
data.forEach(row => {
csvArray.push(Object.values(row).join() + '\n');
});
// 统计进度
// const process = (i / step) * 100;
// console.log(`进度 ${Math.round(process)}%`);
// 适当停顿,避免页面无法执行后续
// await new Promise((_resolve) => {
// setTimeout(() => _resolve(true), 50);
// });
resolve(true);
} catch (error) {
reject(error);
}
})();
});
}
const blob = new Blob([String.fromCharCode(0xfeff), ...csvArray], {
type: "text/plain;charset=utf-8"
});
await FileSaver.saveAs(blob, 'file.csv');
return true;
} catch (error) {
return Promise.reject(error)
}
},
3.简单版实现:
实现了模拟数据的函数,100w条数据,每次数据传2000条
实际在模拟数据生成的时候会对页面造成阻塞
<template>
<button @click="exportCsvs" :disabled="pending">导出 CSV 表格</button>
</template>
<script>
// 普通分片
import Mock from 'mockjs';
import FileSaver from 'file-saver';
export default {
name: 'App',
components: {
},
data() {
return {
csvdata: '',
}
},
created() {
this.getData(10000 * 100);
},
methods: {
async getData(limit) {
return new Promise((resolve, reject) => {
try {
const Random = Mock.Random;
// 创建指定个数的随机数据
const data = new Array(limit).fill('').map((_, index) => {
return {
id: `200820-${index}`,
username: Random.cname(),
url: Random.url('http'),
price: Random.float(0, 110000, 0, 2),
createAt: Random.datetime('yyyy-MM-dd HH:mm:ss'),
};
});
this.csvdata = data
console.log(data);
resolve(data);
} catch (error) {
reject(error);
}
});
},
// 导出数据为 CSV 格式
async exportCsv(total, size) {
try {
if (!total) throw "无数据";
// 分片
const step = Math.ceil(total / size);
// CSV 缓存
let csvArray = [];
// 表头处理 - 一般表头由外部传入
csvArray.push(['编号', '用户名', '官网', '报价', '创建日期'].join() + '\n');
// 通用分片
for (let i = 0; i < step; i++) {
await new Promise((resolve, reject) => {
(async () => {
try {
// 创建指定个数的随机数据
const data = this.csvdata.slice(i, i + size);
// 格式化为 CSV 字符串
data.forEach(row => {
csvArray.push(Object.values(row).join() + '\n');
});
// 统计进度
// const process = (i / step) * 100;
// console.log(`进度 ${Math.round(process)}%`);
// 适当停顿,避免页面无法执行后续
// await new Promise((_resolve) => {
// setTimeout(() => _resolve(true), 50);
// });
resolve(true);
} catch (error) {
reject(error);
}
})();
});
}
const blob = new Blob([String.fromCharCode(0xfeff), ...csvArray], {
type: "text/plain;charset=utf-8"
});
await FileSaver.saveAs(blob, 'file.csv');
return true;
} catch (error) {
return Promise.reject(error)
}
},
// 创建模拟数据
async exportCsvs() {
try {
this.pending = true;
const startTime = performance.now();
await this.exportCsv(10000 * 100, 2000, (process) => {
// 进度条更新
this.csvProcess = process;
});
const endTime = performance.now();
console.log(((endTime - startTime) / 1000).toFixed(2))
} catch (error) {
alert(error);
} finally {
this.pending = false;
}
},
}
}
</script>
<style>
#app {
font-family: Avenir, Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-align: center;
color: #2c3e50;
margin-top: 60px;
}
</style>
时间为6.60s

1363

被折叠的 条评论
为什么被折叠?



