前端大文件分片上传实现与断点续传方案(含完整代码讲解)

在上传大文件(如视频、安装包、模型文件)时,直接上传容易出现以下问题:

  • 文件过大 → 浏览器/服务器容易超时
  • 上传过程中断 → 重新上传浪费时间
  • 网络波动 → 上传失败率高

因此,大文件分片上传 + 断点续传 + 秒传校验 是目前最通用、最稳定的解决方案。

本文将通过一段完整可运行的示例代码,详细讲解如何在前端实现分片上传、断点续传、服务端校验等关键功能。


✨ 实现效果

  • ✔ 自动切片(默认 5MB/片,可配置)
  • ✔ 查询已上传分片(断点续传)
  • ✔ 自动跳过已上传的片段
  • ✔ 每片上传成功后重新校验
  • ✔ 所有片段上传完成后自动触发合并
  • ✔ 错误处理完善

📌 核心代码(uploadLargeFile)

以下代码就是本文的核心逻辑,也是你提供的代码版本,经过梳理解释后会更易理解:

export async function uploadLargeFile({ file, fileId, id, chunkSize = 5 * 1024 * 1024, apiCheckChunks, apiUploadChunk, apiMergeChunks }) { if (!file) throw new Error("file 不能为空"); if (!fileId) throw new Error("fileId 不能为空"); const fileName = file.name; const totalChunks = Math.ceil(file.size / chunkSize); const chunks = []; // 1. 前端文件切片 for (let i = 0; i < totalChunks; i++) { const start = i * chunkSize; const end = Math.min(file.size, start + chunkSize); chunks.push(file.slice(start, end)); } // 2. 查询已上传分片(断点续传) let res = await apiCheckChunks(fileId, id); let uploadedList = Array.isArray(res.data) ? res.data : []; if (!Array.isArray(uploadedList)) uploadedList = []; // 3. 逐片上传 for (let i = 0; i < totalChunks; i++) { if (uploadedList.includes(i)) { console.log(`分片 ${i} 已上传,跳过`); continue; } const formData = new FormData(); formData.append("fileId", fileId); formData.append("id", id); formData.append("chunkIndex", i); formData.append("totalChunks", totalChunks); formData.append("chunk", chunks[i]); await apiUploadChunk(formData); // 上传成功后重新查询列表(确保状态正确) const res1 = await apiCheckChunks(fileId, id); uploadedList = res1.data || []; if (!uploadedList.includes(i)) { throw new Error(`分片 ${i} 上传失败,请重试`); } } // 4. 所有片段上传完成 → 执行合并 if (uploadedList.length === totalChunks) { console.log("所有分片上传完成,开始合并文件"); await apiMergeChunks(fileId, fileName, id); } else { throw new Error("未上传完所有分片,无法合并"); } return true; } 

📘 详细逻辑解析

1. 前端切片(slice 实现)

file.slice(start, end)

浏览器原生提供 slice,因此实现非常简单。

如果选择 5MB 一个片段,1GB 文件会被切成:

Math.ceil(1024MB / 5MB) = 205 片

2. 查询已上传分片(断点续传关键)

let res = await apiCheckChunks(fileId, id); let uploadedList = Array.isArray(res.data) ? res.data : [];

服务端返回的数据通常是:

[0, 3, 5, 6]

前端据此跳过已上传片段,避免重复上传,大幅提升效率。

3. 上传文件分片(FormData)

每个分片上传都附带:

  • 分片 index
  • 总分片数
  • chunk 二进制数据
  • 业务 ID 或用户 ID

这是一个完整的可追踪数据结构,支持合并校验。

4. 每片上传后重新校验(确保上传成功)

const res1 = await apiCheckChunks(fileId, id); uploadedList = res1.data || [];

避免服务器延迟导致状态不同步,确保每片上传成功。

5. 全部上传完毕 → 调用合并

await apiMergeChunks(fileId, fileName, id);

后端将所有片段按顺序合并成最终文件。

🏗 后端接口交互说明(简版)

前端需要的接口:

接口功能
apiCheckChunks(fileId)查询已上传的分片列表
apiUploadChunk(formData)上传某个片段
apiMergeChunks(fileId, fileName)合并所有片段

通常后端会在服务器临时目录中创建:

/upload/tmp/{fileId}/0 /upload/tmp/{fileId}/1 /upload/tmp/{fileId}/2 ...

然后合并成:

/upload/merged/xxx.mp4


💡 常见问题(FAQ)

1. 为什么 uploadedList.includes 报错?

通常是:

  • 服务端返回的数据不是数组
  • res.data 为 null
  • uploadedList 不是数组直接调用 includes 出错

你的代码已经做了兜底处理:

let uploadedList = Array.isArray(res.data) ? res.data : [];

但仍要保证服务端返回值格式正确。


🎯 总结

本文展示了一个完整可用的前端大文件分片上传工具方法,支持:

  • 文件切片
  • 分片校验
  • 断点续传
  • 分片上传
  • 自动合并

其优势是:

  • 前端逻辑清晰
  • 易接入任何 UI(Vue/React/uni-app)
  • 可结合后端实现秒传(加 MD5 校验)
  • 非常适合大文件上传场景

最后如何使用:

 // 父组件提交表单 调用大文件上传 addAndUpload(formData).then(async (res) => { if (res.status === 'success') { this.$message({ message: '操作成功', type: 'success' }); this.file_Id = res.data.fileId loading.close(); this.dialogVisible = false; if (this.upFile !== null) { const fileId = this.file_Id const file = this.upFile this.$message.info("大文件,启动分片上传...") try { await uploadLargeFile({ file, fileId, id: res.data.id, chunkSize: 20 * 1024 * 1024, apiCheckChunks: (fileId, id) => checkChunks({ fileId, id }), apiUploadChunk: (formData) => uploadChunk(formData), apiMergeChunks: (fileId, fileName, id) => mergeChunks({ fileId, fileName, id }) }) this.$message.success("大文件上传完成") } catch (err) { this.$message.error("分片上传失败") console.error(err) } } this.getData(); this.resetForm2(formName); } else { this.$message({ message: res.msg, type: 'warning' }); loading.close(); } }) 

Read more

从零开始构建你的第一个DApp:Web3开发者的入门指南

从零开始构建你的第一个DApp:Web3开发者的入门指南 1. 理解Web3与DApp的基础概念 Web3代表着互联网的下一次进化,它基于区块链技术构建,核心在于去中心化和用户主权。与传统的Web2应用不同,DApp(去中心化应用)运行在区块链网络上,具有以下关键特征: * 去中心化:没有单一控制实体,数据存储在分布式节点上 * 透明性:所有交易记录在公开账本上,可验证但不可篡改 * 代币经济:通过加密货币和智能合约实现价值交换 * 用户主权:用户真正拥有自己的数据和数字资产 典型DApp架构对比: 组件传统应用DApp后端中心化服务器智能合约数据库SQL/NoSQL区块链身份验证用户名/密码加密钱包支付系统银行/支付网关加密货币 以太坊是目前最流行的DApp开发平台,其生态系统提供了完整的工具链。开发DApp需要掌握几个核心概念: 1. 智能合约:自动执行的代码,存储在区块链上 2. Solidity:以太坊智能合约的主要编程语言 3. Web3.js/Ethers.js:与区块链交互的JavaScript库 4. MetaMask:连接DAp

机器人算法十年演进

机器人算法十年演进(2015-2025):从模型驱动的几何计算到具身智能的认知决策范式革命 2015-2025年,机器人算法完成了从「几何与物理模型驱动的专用任务执行」到「数据与大模型驱动的通用具身智能决策」的根本性范式跃迁。作为机器人系统的“大脑与神经中枢”,机器人算法是覆盖感知理解、定位建图、规划控制、标定补偿、决策学习五大核心板块的完整技术体系,直接决定了机器人的环境适应性、作业精度、自主决策能力与智能化水平,是连接硬件本体与场景应用的核心桥梁。 这十年,机器人算法的演进始终与机器人产业从「单机工业自动化→柔性场景规模化→通用具身智能化」的发展节奏完全同频,与硬件本体、软件架构、平台化技术的迭代深度耦合,完整见证了机器人从“只能在静态产线执行固定程序”到“可在全场景自主完成复杂任务”的能力跨越,同时实现了中国机器人算法从完全技术跟随、海外垄断,到全栈自主可控、部分领域全球领跑的产业格局巨变。 本文与此前机器人系统、软件架构、规控、感知、定位等系列内容形成完整闭环,聚焦算法的范式迭代、工程化落地、能力边界与产业价值,完整还原机器人算法十年间的四次代际跃迁。 一、核心演进四

VR大空间项目内容规划与设计的市场经验总结(2023-2026)

VR大空间项目内容规划与设计的市场经验总结(2023-2026) 引言:从元年到爆发,VR大空间的三年演进 2023年,随着《消失的法老》在上海太古汇的惊艳亮相,中国VR大空间行业迎来了自己的“元年”。这部由HTC联合法国Emissive工作室、哈佛大学吉萨考古团队打造的沉浸式体验,以45分钟超长时长、800平方米自由移动空间、毫米级金字塔还原三大核心优势,在11个月运营期内吸引约11万人次参与,总票房突破3000万元。这一现象级作品不仅重新定义了VR体验的行业标准,更直接推动了上海文旅局将VR大空间纳入“智慧旅游创新示范工程”。 三年后的今天,VR大空间已从零星试点发展为遍地开花的成熟业态。据VR陀螺不完全统计,仅2025年上半年就有超100个VR大空间项目落地,叫得上名字的20家运营商门店总数突破1000家。国际数据公司(IDC)预测,2025年全球VR大空间解决方案市场规模将突破120亿美元,年复合增长率高达58%,其中中国市场规模占全球比重预计超40%。 然而,繁荣之下暗流涌动。行业在快速扩张的同时,也面临着内容同质化、复购率低、盈利模式单一等深层挑战。本文将从产品总

柔性抓取的“慧眼”:MEMS 3D视觉如何让机器人精准识别无序堆叠的复杂钣金件?

在汽车零部件、家电外壳等行业,杂乱堆叠的钣金件是自动化产线最后也是最难的堡垒之一。传统机器人依靠示教和固定轨迹,面对这些反光、形状多变、易形变且姿态随机的工件时束手无策。而基于MEMS微振镜的3D视觉技术,正以其 “精准、快速、抗干扰” 的特性,成为赋予机器人柔性抓取能力的“慧眼”,从根本上解决了这一行业痛点。 一、 无序抓取的“魔鬼细节”:为何传统方案失灵? 针对复杂钣金件,柔性抓取面临四大核心挑战,这正是MEMS 3D视觉技术的用武之地: 挑战具体描述传统方案的局限MEMS 3D视觉的优势切入点1. 强反光与多噪点金属表面产生镜面反射,导致过曝或形成伪像。2D视觉完全失效;普通结构光会产生大量噪点和数据缺失。可编程扫描策略,通过多曝光融合、自适应激光功率调节,获取完整点云。2. 复杂三维姿态识别工件任意堆叠,存在遮挡、倾斜、嵌套,需精确计算6D位姿。2D视觉无法获得深度信息;线激光扫描速度慢,无法应对复杂堆叠。高速面扫描,在毫秒级内获取完整场景的稠密点云,支持复杂位姿解算。3. 工件形变与种类多变薄板件易弯曲,且产线常需处理多品种、小批量的工件。