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

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

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

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

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


✨ 实现效果

  • ✔ 自动切片(默认 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

实战Pi0机器人控制中心:轻松实现机器人智能操控

实战Pi0机器人控制中心:轻松实现机器人智能操控 1. 项目概述:重新定义机器人控制体验 Pi0机器人控制中心是一个基于先进视觉-语言-动作模型的智能操控平台,它彻底改变了传统机器人控制的复杂方式。这个项目将多视角视觉感知、自然语言理解和精准动作控制完美融合,让机器人操控变得像与人对话一样简单直观。 想象一下,你只需要对机器人说"捡起那个红色方块",它就能准确理解并执行相应动作。这就是Pi0控制中心带来的革命性体验——无需编写复杂的控制代码,无需记忆繁琐的操作指令,用最自然的方式与机器人进行交互。 这个控制中心采用全屏Web界面设计,界面简洁现代,操作流程直观。无论你是机器人技术爱好者、研究人员,还是教育工作者,都能快速上手使用,专注于机器人应用开发而不是底层技术实现。 2. 核心功能详解:智能操控的四大支柱 2.1 多视角视觉感知系统 Pi0控制中心支持同时输入三个不同角度的环境图像:主视角、侧视角和俯视角。这种多视角设计模拟了人类观察环境的自然方式,为机器人提供了全面的环境感知能力。 * 主视角摄像头:提供机器人正前方的视野,用于识别主要操作对象 * 侧视角

By Ne0inhk

AI × 低代码 × 工程化:Oinone Pamirs 的下一代产品化引擎实践

AI × 低代码 × 工程化:Oinone Pamirs 的下一代产品化引擎实践 一、传统企业软件交付的「不可能三角」困境 在传统企业软件开发领域,长期存在一个被称为「不可能三角」的困境:交付速度、产品质量与成本控制三者难以兼得。追求快速上线往往牺牲稳定性;强调高质量则拖慢节奏;控制成本又可能导致功能缩水或技术债堆积。尤其在定制化项目泛滥的行业(如政务、金融、制造),软件公司常年陷于「接单—开发—维护—再接单」的恶性循环中,难以形成可复用的产品资产。 1.1 项目制开发的致命缺陷 当前,大量中小型软件公司仍采用「项目制」开发模式:每个客户提出差异化需求,团队便从零开始编码,最终交付一套高度定制化的系统。这种模式看似灵活,实则代价高昂: * 代码无法复用:相似功能(如用户管理、审批流、报表)在不同项目中反复重写 * 维护成本指数级增长:十个客户意味着十套独立系统,

By Ne0inhk

本地AI绘画新选择:Z-Image-Turbo_UI界面真实体验

本地AI绘画新选择:Z-Image-Turbo_UI界面真实体验 最近在测试几款轻量级本地AI绘图工具时,偶然发现了一个特别“省心”的方案——Z-Image-Turbo_UI界面。它不像传统Stable Diffusion整合包那样动辄要配环境、装依赖、调参数,而是直接跑起一个干净的Gradio界面,打开浏览器就能用。更关键的是:不联网、不传图、不依赖云服务,所有生成过程都在你自己的电脑里完成。我用一台RTX 3060笔记本实测了三天,从启动到出图、从修图到批量保存,全程没报错、没卡死、没弹出任何奇怪的警告框。这篇文章就带你完整走一遍真实使用流程,不讲虚的,只说你打开后真正会遇到什么、怎么操作、效果如何、哪些地方值得多点两下。 1. 为什么说它“开箱即用”?——零配置启动体验 很多新手被劝退,不是因为不会写提示词,而是卡在第一步:环境装不上、CUDA版本对不上、模型路径找不到……Z-Image-Turbo_UI绕开了所有这些坑。 它本质是一个预打包的Python脚本+模型权重+Gradio前端的组合体,所有依赖都已内置。你不需要:

By Ne0inhk

vitis安装图文教程:零基础入门FPGA开发环境配置

手把手带你完成 Vitis 安装:从零搭建 FPGA 开发环境 你是不是也曾在搜索“vitis安装”时,被一堆术语、版本号和报错信息搞得晕头转向?明明只是想开始学 FPGA,怎么第一步就卡在了环境配置上? 别急。这篇文章不玩虚的,也不甩文档链接。我会像一个老工程师坐在你旁边一样,一步步带你把 Vitis 装好、跑通、用起来。无论你是电子专业学生、转行嵌入式的新手,还是对硬件加速感兴趣的软件开发者,只要跟着走,2小时内你就能拥有一个完整可用的 FPGA + SoC 开发环境。 为什么是 Vitis?它到底解决了什么问题? 先说清楚一件事: Vitis 不是你传统印象里的 FPGA 工具 。 以前做 FPGA,得写 Verilog/VHDL,画电路图,综合布局布线……门槛高、周期长。而今天很多项目——比如图像识别、

By Ne0inhk