跳转到内容

大文件切片上传场景

💡

大文件切片上传是处理大文件(视频、镜像、数据集等)的标准方案。核心思路:前端将大文件切分为多个小片段(Chunk),逐片上传到后端,后端存储到MinIO/OSS,全部上传完成后合并为一个完整文件。配合MD5校验实现秒传断点续传


一、核心流程总览

三大核心流程:秒传(MD5去重)→ 分片上传(并发上传到MinIO)→ 合并文件(前端触发合并请求)。断点续传作为增强功能贯穿其中。

1.1 整体架构图


二、核心流程详解

2.1 流程一:秒传(MD5去重检测)

📌

原理:文件MD5值是其内容的唯一指纹。如果服务端已存储过相同MD5的文件,直接返回文件URL,跳过上传过程,实现"秒传"。

接口设计

场景

处理

MD5已存在且文件完整

秒传,直接返回已有文件URL,跳过上传

MD5已存在但文件不完整

返回已上传的分片索引列表(断点续传)

MD5不存在

全新上传,前端开始分片上传


2.2 流程二:分片上传

📌

前端:使用 File.slice() 将文件切分,通过 Web Worker 计算MD5,并发上传分片。后端:接收每个分片,直接写入MinIO的临时目录,Redis记录分片上传状态。

前端核心代码

后端分片上传接口

分片元数据设计

并发控制要点

  • 前端并发数:控制在3-5个(浏览器有同域并发连接限制,Chrome默认6个)
  • 分片大小:建议5MB-10MB每片(MinIO单次PUT上限5TB)
  • 失败重试:单分片失败自动重试3次,指数退避
  • 进度上报:(已上传分片数 / 总分片数) × 100%

2.3 流程三:合并文件

📌

所有分片上传完成后,前端请求合并接口。后端调用MinIO的composeObject API,将多个分片对象按顺序合并为一个完整的文件对象。MinIO的compose操作是服务端操作,不经过后端服务器,不消耗带宽

MinIO compose限制:单次compose最多合并1000个源对象。如果超过1000个分片,需要分批compose:先每1000个合并为中间对象,再合并中间对象为最终文件。


三、断点续传

📌

断点续传的核心:前端在秒传检查阶段获取已上传的分片列表 → 跳过已上传的分片 → 只上传缺失的分片 → 全部完成后同样请求合并。

3.1 实现方案

方案

实现

Redis存储(推荐)

Key: upload:chunks:{fileMd5} Value: Set<Integer>(已上传的chunkIndex集合)。设置过期时间(24h),过期后未合并则需重新上传

MinIO本身

每次上传前通过 minioClient.statObject() 检查分片是否已存在于MinIO,存在则跳过

前端localStorage

前端本地记录已上传分片列表,刷新页面也能恢复(辅助方案)

3.2 断点续传check接口增强


四、完整数据库设计

字段

类型

说明

id

bigint

主键

file_md5

varchar(64)

文件MD5值(唯一索引)

file_name

varchar(255)

原始文件名

file_size

bigint

文件大小(字节)

storage_path

varchar(500)

MinIO中的对象路径

total_chunks

int

总分片数

chunk_size

bigint

单片大小(字节)

status

tinyint

0=UPLOADING / 1=COMPLETED / 2=MERGING / 3=FAILED

create_time

datetime

创建时间

update_time

datetime

更新时间


五、边界与异常处理

场景

处理方案

单个分片上传失败

前端自动重试3次,指数退避(1s→2s→4s),仍失败则上报用户

网络中断恢复

断点续传:重新调用check接口获取已上传分片,跳过已上传的

浏览器关闭后重开

localStorage存(fileMd5 + totalChunks),刷新后恢复上传状态

并发上传同一文件

秒传检查阶段发现文件已COMPLETED,直接返回URL(乐观锁)

分片超1000个

分批compose合并(每1000片合并为中间对象,最终再合并中间对象)

合并过程中断

合并前设置status=MERGING,合并成功后设为COMPLETED。定时任务清理超时MERGING状态并重试

Redis分片记录过期

Redis key设置TTL=24h。过期后重新查询MinIO已有分片重建记录

文件为空

前端上传前检查file.size > 0;后端拒绝size=0的分片


六、你项目中的集成方案

这个方案可以完整集成到你的Spring Boot项目中:

  1. 新增依赖:minio(S3 SDK)+ spring-boot-starter-data-redis + SparkMD5(前端)
  2. 新增接口:/upload/check、/upload/chunk、/upload/merge 三个接口
  3. 新增表:t_file_info(文件记录表,字段如上表)
  4. 配置MinIO:application.yml中配置minio.endpoint/accessKey/secretKey/bucket
  5. 前端改造:引入SparkMD5计算文件MD5 + File.slice()切片 + 并发上传逻辑
  6. Redis:使用SET存储已上传分片索引,TTL=24h

💡

效果总结:

  • 秒传:相同文件(同MD5)跳过上传,直接复用,节省带宽和时间
  • 切片上传:大文件分片并发上传,速度提升3-5倍
  • 断点续传:网络中断后只上传未完成的分片,不从头开始
  • MinIO compose:合并操作在服务端完成,不消耗后端带宽
  • MD5校验:文件级MD5防重复,分片级MD5防传输错误