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

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

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

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

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


✨ 实现效果

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

国内如何升级GitHub Copilot到专业版

国内如何升级GitHub Copilot到专业版

国内外的AI编程工具我用过很多,用的时间比较长的是Cursor,后来Cursor在国内不能用了,就又回去试了一下GitHub Copilot,结果被惊艳到了,在VS Code里用起来很丝滑,体验很好,感觉VS Code团队在AI编程这块上真是下功夫了,现在其体验已经不输Cursor。 我一直是VS Code的粉丝,感觉还是原生的VS Code用起来最舒服,现在VS Code里的Copilot体验已经做的很好,就没有理由再用其他替代编辑器了。 VS Code里的Copilot每月有一定的免费额度,用完之后就需要开通专业版才能继续使用。我用完免费额度之后,已经被其良好的体验所打动,就想升级到专业版,但是如何付费成了问题。在网上搜了一下,说是国内的信用卡不能用,而之前好用的wildcard虚拟信用卡服务现在也停了,试了一下网友推荐的胡桃卡,试了好几次也没有支付成功,还被扣了很多手续费。 现在还有什么方式能支付升级到copilot专业版呢? 后来发现GitHub Copilot升级页面上的支付方式那里也支持paypal,就在Payment method那里,credit card旁边有

llama.cpp量化模型部署实战:从模型转换到API服务

1. 为什么你需要关注llama.cpp:让大模型在普通电脑上跑起来 如果你对AI大模型感兴趣,肯定听说过动辄需要几十GB显存的“庞然大物”。想在自己的电脑上跑一个7B参数的模型,以前可能得配一张昂贵的专业显卡。但现在,情况不一样了。我今天要跟你聊的 llama.cpp,就是那个能让大模型“瘦身”并飞入寻常百姓家的神奇工具。 简单来说,llama.cpp是一个用C/C++编写的开源项目,它的核心目标只有一个:用最高效的方式,在消费级硬件(比如你的笔记本电脑CPU)上运行大型语言模型。它不像PyTorch那样是个庞大的深度学习框架,它更像一个“推理引擎”,专注于把训练好的模型,以最小的资源消耗跑起来。 我刚开始接触大模型部署时,也被各种复杂的依赖和巨大的资源需求劝退过。直到用了llama.cpp,我才发现,原来在我的MacBook Pro上,也能流畅地和Llama 2这样的模型对话。这背后的功臣,主要就是两点:纯C/C++实现带来的极致性能,以及模型量化技术带来的体积与速度革命。量化这个词听起来有点技术,你可以把它想象成给模型“压缩图片”

AutoGPT与Stable Diffusion结合使用:实现文本到图像的全自动创作

AutoGPT与Stable Diffusion结合使用:实现文本到图像的全自动创作 在创意内容生产领域,一个正在悄然发生的变化是:AI不再只是“你问我答”的工具,而是开始扮演起能独立思考、主动执行的“协作者”角色。想象这样一个场景——你只需说一句:“帮我为‘Morning Brew’咖啡馆设计一张温暖风格的宣传海报”,几分钟后,一份包含高质量图像、匹配文案甚至多轮优化建议的完整设计方案就已生成完毕。这并非科幻情节,而是通过AutoGPT + Stable Diffusion这一组合可以实现的真实工作流。 传统的内容创作流程中,从构思到成图往往需要经历多个割裂的环节:用户先手动撰写提示词,再切换到图像生成平台进行渲染,若效果不佳还需反复调整描述、重新生成。整个过程不仅耗时,还高度依赖使用者对提示工程的理解和审美判断力。而当我们将具备自主推理能力的AutoGPT与擅长视觉表达的Stable Diffusion深度融合时,一条从“意图理解”到“图像输出”的端到端自动化路径便得以打通。 从“问答机器”到“行动代理”:AutoGPT如何让LLM真正动起来? 大型语言模型(LLM)的强

vs code 中内置的聊天是 GitHub Copilot Chat 吗

vs code 中内置的聊天是 GitHub Copilot Chat 吗

vs code 中内置的聊天是 GitHub Copilot Chat 吗 vs code 中内置的聊天要分情况讨论: 1. VS Code 内置的聊天(“Ask Cody”):不是 GitHub Copilot Chat VS Code 在 2023 年底(1.85 版本)引入了一个内置的聊天侧边栏,它的默认提供者是 VS Code 自己的 AI 助手 “Cody”。 * 这个功能是 VS Code 编辑器的一部分,图标通常是一个对话框气泡 💬。 * 它的目标是提供与编辑器深度集成的通用编程帮助,例如解释代码、生成代码、问答等。 * 它不一定与你的 GitHub Copilot 订阅绑定,即使你没有订阅