大文件上传👈 | React + NestJs |分片、断点续传、秒传🚀 , 你是否知道 ???

前言

大文件上传不能一次性将整个大文件直接上传,因为这可能会导致

  • 内存占用过高、
  • 网络传输不稳定等问题

所以通常的做法是把大文件分割成一个个小块,分别上传这些小块,最后在服务器端将这些小块合并成完整的文件。

同时,为了支持秒传和断点续传功能,还需要对文件进行哈希计算,通过哈希值来判断文件是否已经上传过,以及哪些小块已经上传。

项目地址 : 大文件上传demo

前端 vue 和 react 均实现 , 后端 Nest 实现 , 代码可以运行 , 点个赞吧~

前端效果如图:

后端效果如图: 文件上传 ,之后 , 我保存到 uploads 文件夹下 :

大文件上传流程

和倔友一样 , 文字太多 ,很有压力 ,于是乎画了一张图😀 , 不知可否点个赞 ~

外层数字序号是上图解析 , 内层序号是实现细节 , 可先看外层数字序号

  1. 前端选择文件后,计算文件哈希值并分割文件(文件分片
    1. antd 提供的Upload.Dragger 实现拖拽区域
    2. SparkMD5 计算哈希值
    3. file.slice 方法分割文件
  2. 前端发送请求到后端检查文件上传状态
    1. 前端 axios 向后端提供的接口发送请求
    2. 后端接口返回 uploaded 、uploading 两种状态(未上传是默认状态)
  3. 前端根据后端返回的状态决策
    1. 返回 uploading ,上传还未上传的文件块 , 即断点续传
    2. 返回 uploaded , 文件已经上传 , 告诉用户已经上传 , 即秒传
    3. 默认未上传 , 则执行上传文件操作
  4. 步骤 3 中 1,3 所有文件块上传完成后,前端发送请求通知后端合并文件块。
  5. 后端将文件块合并成完整的文件 , 并先前端响应成功信息

通过上述这种方式,前端和后端相互配合,实现了大文件的上传、秒传和断点续传功能。

接下来 , 具体看看代码如何实现 ~

代码实现

前端使用 React + TS

  1. axios: 基于 promise 向后端发送 HTTP 请求
  2. spark-md5 : 使用哈希算法计算文件的哈希值
  3. antd: 引入上传文件的组件
  4. TypeScript : 增强代码健壮性

后端使用 NestJs + TS

  1. NestJS:一个用于构建高效、可靠和可扩展的服务器端应用程序的渐进式 Node.js 框架。
  2. Multer :用于处理 multipart/form-data 的中间件,主要用于上传文件。
  3. TypeScript:NestJs 支持 TS
  4. Node.js 文件系统 (fs) 模块:用于与文件系统交互,如读取、写入和删除文件和目录。

初次之外是一些语法检查工具 ESlint

导库

代码总体结构如下 :

UI

首先写 App 函数 , 实现利用 Upload.Dragger 实现上传 UI

添加处理函数 handChange , 若文件有效 , 进入handFileUpload 函数中 , 进行

  • 文件分片 , MD5 哈希值计算
  • 检查文件上传状态 , 与后端不断交互

哈希计算与分片

在handFileUpload 中 , 实现文件分片 , MD5 哈希值计算

计算MD5 哈希值我们封装的函数如下 : 使用 Spark-md5 库

文件上传状态分流

handFileUpload 计算哈希值 和 实现文件分片后 ,

首先检查文件上传情况 , 向后端发一个请求 , 发送 hash 和 文件名 以及文件块的长度

后端通过 Query 从 params 中获取这三个字段

通过检查 uploads 目录下 , 是否有完整文件或文档块来决定返回'uploaded'(秒传)还是'uploading'(断点续传)

之后根据这些状态 , 选择合适的处理方法

如果是秒传 , 直接告诉用户成功 ; 未上传状态和部分上传状态 , 会进入下面的代码 , 请求后端:http://localhost:3000/upload 接口 , 在后端创建文件夹 , 并且保存分块

分块合并

最后继续执行前端下面的逻辑 , 请求后端将分块合并

后端的实现如下 :

如此大文件上传流程走完 ~

总结

把上面这张图拿下来 , :

面试官 : 请说说大文件上传 ?

你 : 掏出掘金看完这篇文章 , 开始你的表演 ~

优化点

前端切片

切片后 , 如果用户突然关掉浏览器 , 可以将 blob(二进制大对象) , 储存到 IndexedDB , 下次用户近来时候 ,

嗅探一下是否存在未完成的切片

使用 websocket 双向通信 , 实时通知 和请求序列控制

......

下次 , 在来 , 关注我 , 点个赞 , 我酱油更大的动力 , 用心写文章 !

相关推荐
用户938515635072 小时前
从零在浏览器里跑 DeepSeek-R1:WebGPU + Transformer.js 全链路实战
前端·设计模式·typescript
CodeSheep2 小时前
稚晖君公司人事大变动,来了!
前端·后端·程序员
鱼樱前端3 小时前
用 AI 做内容变收入
前端·人工智能·ai编程
浮生望3 小时前
React + TypeScript 组件设计进阶:从类型约束到无状态组件的三次进化
前端
90后的晨仔3 小时前
Mac 开发 uni-app 终极方案:让安卓模拟器彻底脱离 Android Studio 独立运行
前端·vue.js
90后的晨仔4 小时前
别再搞混了!uni-app 中 node_modules 和 uni_modules 到底是什么关系?
前端
kyriewen4 小时前
面试官问"这段逻辑为什么这样写"——我才发现,这半年我写的代码,我自己都解释不了
前端·javascript·面试
谢小飞5 小时前
大文件上传很难?学会这招,GB文件秒传不是梦
前端·node.js
程序员黑豆5 小时前
Windows 系统 Java 环境变量配置全攻略:解决“不是内部或外部命令”
java·前端·ai编程
To_OC5 小时前
别只拿 useRef 绑 DOM 了,搭配 Web Worker 解决页面卡顿才是真的香
前端·react.js·dom