springboot实现使用断点续传优化同步导入Excel
需求前言
在跨境电商系统中,其中下单方式之一就是通过Excel记录多个用户该下单哪些商品实现批量下单,就需要实现导入Excel的方案,最简单的就是同步导入Excel,但同步导入大Excel文件时,网络原因抑或误刷新了页面,就需要重新上传,这就造成用户体验感不好,于是引入断点续传来优化同步导入Excel。
断点续传
断点续传就是在文件上传或下载过程中,如果中途中断了,下次可以从中断的地方继续,而不需要重新开始。这对于大文件传输特别有用,节省时间和带宽。
前端部分需要支持分片上传。也就是说,把大文件切成多个小块,每个小块单独上传。这样即使中间断了,只需要传剩下的部分。前端怎么做呢?本文使用JavaScript的File API来读取文件,然后分片。比如用File.slice方法,把文件切成多个Blob。然后每个Blob单独上传,并告诉服务器这是第几个分片,总共有多少分片,文件的唯一标识是什么,比如用MD5哈希之类的。这样服务器就知道怎么合并这些分片了。
然后,后端操作需要接收这些分片,保存起来,并且记录哪些分片已经上传了。当所有分片都上传完后,后端要把这些分片按顺序合并成完整的文件。这里可能涉及到文件存储的问题,每个分片保存为临时文件,最后合并的时候可能需要按顺序读取所有分片然后写入到一个文件中。另外,为了支持断点续传,前端在上传前可能需要先询问服务器,这个文件已经传了哪些分片,然后只传剩下的。所以后端还需要提供一个接口,让前端可以查询某个文件的上传进度。
具体步骤:
1、前端选择文件后,先计算文件的唯一标识(比如MD5),并查询服务器该文件的上传情况,获取已上传的分片列表。
2、根据分片大小(比如1MB),将文件分片。
3、遍历所有分片,对于未上传的分片,逐个上传到服务器。
4、每个分片上传时,携带分片索引、总片数、文件唯一标识等信息。
5、后端接收到分片后,保存分片文件,并记录该分片已上传。
6、当所有分片上传完毕后,前端发送一个合并请求,或者后端检测到所有分片都已上传后自动合并分片为完整文件。
7、合并完成后,删除临时分片文件。
前端实现
<input type="file" id="fileInput" accept=".xlsx,.xls" />
<button onclick="startUpload()">上传Excel</button>
<div id="progress"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/spark-md5/3.0.0/spark-md5.min.js"></script>
<script>
const CHUNK_SIZE = 2 * 1024 * 1024; // 2MB分片
async function startUpload() {
const file = document.getElementById('fileInput').files[0];
if (!file || !file.name.match(/\.(xlsx|xls)$/i)) {
alert('请选择Excel文件');
return;
}
// 1. 生成文件唯一标识
const fileId = await computeFileHash(file);
document.getElementById('progress').innerHTML = '正在验证文件...';
// 2. 检查文件状态
const {
exists, uploadedChunks } = await fetch(`/api/upload/check?fileId=${
fileId}`)
.then(res => res.json());
if (exists) {
document.getElementById('progress').innerHTML = '文件已存在,直接解析';
triggerParse(fileId); // 触发后端解析
return;
}
// 3. 分片上传
const totalChunks = Math.ceil(file.size / CHUNK_SIZE);
let uploaded = uploadedChunks.length;
// 上传未完成的分片(带进度显示)
for (let i = 0; i < totalChunks; i++) {
if (!uploadedChunks.includes(i)) {
await uploadChunk(file, i, fileId);
uploaded++</

最低0.47元/天 解锁文章
1284

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



