前言
本文采用前后端结合,后端给前端每个分片的上传临时凭证,前端请求临时url,通过后端间接的去上传分片。其实无关乎 vue
或者 react
,思路都是一样的,逻辑也全都是 js 写的,跟模板语法或者 jsx 也没关系,仅仅是赋值不一样而已。
前端:React + TypeScript + Antd + axios + spark-md5 + p-limit + immer
后端:Springboot 3.x + minio + mybatisplus + redis + lombok + hutool-core
前后端的依赖都是最新版。gitee 地址: https://gitee.com/jsonqi/minio-spring-react
前端的 p-limit
是限制请求并发的,不能因为上传文件将请求占满而影响正常业务请求,immer
是为了更方便修改 state 数据,这两个非必须。
为什么不直接前端对接 minio,而要走后端?
- 直接在前端搭建 minio 环境,如果后端给临时凭证让前端直传,后端是无法感知到文件的存入和变动
- 大文件是必须要入数据库的,否则秒传是无法实现的。
为什么要给前端每个分片的 url 上传,而不是前端将每个分片给后端,后端存入 minio?
- 若让前端每个分片都请求后端,后端再将分片传给 minio,势必会造成带宽占用和增大服务器压力
- 后端生成的分片 url 也是临时凭证 url,可以将时效性尽量降低,来确保文件服务器的安全性。(若对安全性有及其严格的考究另说)
功能点
- 小文件和大文件信息都会入库,即都过秒传,尽可能减少服务器冗余文件
- 只有大文件需要分片和合并
- 进度条展示
功能效果图
展示及请求
前端控制台
目录结构
一个文件的上传,对接后端的请求有三个
- 点击上传时,请求 <检查文件 md5> 接口,判断文件的状态(已存在、未存在、传输部分)
- 根据不同的状态,通过 <初始化分片上传地址>,得到该文件的分片地址
- 前端将分片地址和分片文件一一对应进行上传,这步直接对接 minio
- 上传完毕,调用 <合并文件> 接口,合并文件,文件数据入库
大文件分片流程
整体步骤:
- 前端计算文件 md5,并发请求查询此文件的状态
- 若文件已上传,则后端直接返回上传成功,并返回 url 地址
- 若文件未上传,则前端请求初始化分片接口,返回上传地址。循环将分片文件和分片地址一一对一应
- 若文件上传一部分,后端会返回该文件的
uploadId
(minio中的文件标识)和listParts
(已上传的分片索引),前端请求初始化分片接口,后端重新生成上传地址。前端循环将已上传的分片过滤掉,未上传的分片和分片地址一一对应。 - 前端通过分片地址将分片文件一一上传
- 上传完毕后,前端调用合并分片接口
- 后端判断该文件是单片还是分片,单片则不走合并,仅信息入库,分片则先合并,再信息入库。删除 redis 中的文件信息,返回文件地址。
标签:断点续传,Springboot,文件,前端,React,地址,分片,上传,minio From: https://www.cnblogs.com/jsonq/p/18186340该 bucket 开启了公共只读,所以链接地址是可以直接后台拼接的。