searchusermenu
  • 发布文章
  • 消息中心
点赞
收藏
评论
分享
原创

使用Minio实现大文件的分片上传

2023-11-01 01:28:54
817
0

1,背景

在Form表单中上传文件,一般使用下面的流程,先上传文件到minio,然后提交表单数据。

注意:有些用户可能上传了文件而没有提交表单,得定期清理。

对于大文件上传,需要额外考虑上传中断问题(中断可能是因为网络抖动原因,也可能是文件太大,导致请求超时)

针对这个问题已经有比较成熟的方案了,就是分片上传。

2,分片上传

主要流程:

1)把大文件分隔成多个小文件(每个20M)

2)逐个/并发上传小文件

3)等所有小文件都上传完后,调用合并接口将多个小文件合并成大文件

 

前后端交互流程:

浏览器:我准备上传一个大文件,大小为1024MB,MD5为 abc321

后端:好的,请将大文件按20M/块进行分割,编号1-52的数据块都需要上传,上传代号为A

浏览器:这是代号A编号1的数据块,数据块MD5为xxx,请接收

后端:好的,接收完毕,MD5相同,数据块完整

浏览器:这是.....

后端:好的......

......中断......

浏览器:我准备上传一个大文件,大小为1024MB,MD5为 abc321

后端:好的,请将大文件按20M/块进行分割,编号30、36-52的数据块需要上传(其他部分之前上传过),上传代号为A

浏览器:这是代号A编号30的数据块,数据块MD5为xxx,请接收

后端:好的,接收完毕,MD5相同,数据块完整

浏览器:这是.....

后端:好的......

浏览器:数据块上传完毕,请将代号A的文件合并

后端:好的,合并成功

 

从上面的流程可以看出,分片上传主要需要3个接口,

1)开启一个上传任务接口,返回:切片大小,需要上传的分片编号,任务上传ID

2)上传分片接口

3)合并所有分片接口

那接下来我们看下Minio是否提供了这些接口

3,Minio的分片上传接口

MinioAsyncClient继承了S3Base类,提供了S3Base自带的分片上传能力(我这里用的是8.5.1版本,较早的版本可以在MinioClient类中找到类似的方法)

createMultipartUploadAsync       // 创建文件上传任务
listMultipartUploadsAsync       //  查询文件上传任务
uploadPartAsync                  // 上传分片
listPartsAsync                   // 获取分片上传列表
completeMultipartUploadAsync     // 合并分片文件

注意:上面的方法都是protected方法,需要继承MinioAsyncClient这个类把这几个方法都开放出来。

如果需要实现分片和续传功能,还需要对这些接口进行封装

接口1:开启一个上传任务接口

  • 需要前端先计算文件大小和文件MD5
  • 后端根据文件MD5查询Minio中是否已经存在这个上传任务
  • 有则再查询哪些分片已经上传,无则创建一个上传任务
  • 根据一个固定的分片大小(例如20M)计算出分片块的数量
  • 根据已上传分片编号列表,计算出待上传的分片编号列表
  • 将上传任务ID、分片大小、待上传的分片编号列表返回给前端

接口2:上传分片接口

上传分片接口有两种方式,

1)后端中转,前端先将分片传给后端,后端再上传给Minio

2)前端直传,前端使用Minio的预上传Url(Presigned URL),直接将文件上传到Minio

Minio提供一种 Presigned Url ,把上传操作和认证操作分开,这样的好处是减少一次网络传输

如果使用这种方式,接口1中需要给每个待上传的分片获取一个PresignedURL(getPresignedObjectUrl方法),然后将这些URL全部返回给前端

接口3:合并所有分片接口

  • 查询这个上传任务的所有分片
  • 将所有分片合并成一个大文件
  • 返回大文件的路径以及其他信息

 

这里主要是给出使用Minio实现分片上传的思路,有兴趣的小伙伴不妨自己动手实现一下。

0条评论
0 / 1000