spring boot 实现Minio分片上传

简介: spring boot 实现Minio分片上传

应用场景

分片上传,就是将所要上传的文件,按照一定的大小,将整个文件分隔成多个数据块(我们称之为Part)来进行分别上传,上传完之后再由服务端对所有上传的文件进行汇总整合成原始的文件。

分片上传的场景

  • 大文件上传
  • 网络环境环境不好,存在需要重传风险的场景

分片上传的步骤

image.png

前端上传文件的MD5值

判断是否上传过文件

创建文件存储用于存储分块

前端上传文件的MD5值和分块文件的序号

通过序号判断是否包含该分块

前端上传分块

存储分块

是否是最后一块

合并分块

返回文件的存储路径

检查文件的代码

在文件第一次上传时,上传文件的md5值,从而判断文件是否存在minio中

public Result<Boolean> checkFile(String fileMd5) {
        //正常做业务时应该先从数据库中查询
            //如果数据库存在再查询 minio
            GetObjectArgs getObjectArgs = GetObjectArgs.builder()
                    .bucket(bucketName)
                    //                    todo 这里固定了文件的后缀,实际情况下应该从数据库开始查询,得到文件的路径
                    .object(getFilePathByMd5(fileMd5,"png"))
                    .build();
            //查询远程服务获取到一个流对象
            try {
                FilterInputStream inputStream = minioClient.getObject(getObjectArgs);
                if(inputStream!=null){
                    //文件已存在
                    return Result.success(true);
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        //文件不存在
        return Result.success(false);
        }

检查分块的代码

检查分块是前端把需要上传的文件经过大小计算后,算出分块的数量,然后把循环发送文件的md5值和分块序号,然后在minio中检查对应文件夹下是否有对应的分块,如果检查到某一处没有对应的分块,便知道传输中断的位置。

public Result<Boolean> checkChunk(String fileMd5, int chunkIndex) {
        //根据md5得到分块文件所在目录的路径
        String chunkFileFolderPath = getChunkFileFolderPath(fileMd5);
        //如果数据库存在再查询 minio
        GetObjectArgs getObjectArgs = GetObjectArgs.builder()
                .bucket(bucketName)
                .object(chunkFileFolderPath+chunkIndex)
                .build();
        //查询远程服务获取到一个流对象
        try {
            FilterInputStream inputStream = minioClient.getObject(getObjectArgs);
            if(inputStream!=null){
                //文件已存在
                return Result.success(true);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        //文件不存在
        return Result.success(false);
    }

上传分块的代码

public Result uploadChunk(String fileMd5, int chunk, String localChunkFilePath) {
        //分块文件的路径
        String chunkFilePath = getChunkFileFolderPath(fileMd5) + chunk;
        //获取mimeType
        String mimeType = localChunkFilePath.substring(localChunkFilePath.lastIndexOf("."));
        //将分块文件上传到minio
        boolean b = addMediaFilesToMinIO(localChunkFilePath, mimeType, bucketName, chunkFilePath);
        if(!b){
            return Result.error("上传分块文件失败");
        }
        //上传成功
        return Result.success(true);
    }

合并分块的代码

合并分块文件之前,需要检查文件是否和源文件相同,我们通过把分块合并后取文件的md5值和传输过来的MD5值作比较,如果相同则证明传输正确,把合并后的文件存入minio中,并清除分块文件

public Result mergechunks(String fileMd5, int chunkTotal) {
        //分块文件所在目录
        String chunkFileFolderPath = getChunkFileFolderPath(fileMd5);
        //找到所有的分块文件
        List<ComposeSource> sources = Stream.iterate(0, i -> ++i)
                .limit(chunkTotal).map(i -> ComposeSource.builder()
                        .bucket(bucketName)
                        .object(chunkFileFolderPath + i).build()).collect(Collectors.toList());
        //合并后文件的objectname
        String objectName = getFilePathByMd5(fileMd5, "png");
        //指定合并后的objectName等信息
        ComposeObjectArgs composeObjectArgs = ComposeObjectArgs.builder()
                .bucket(bucketName)
                .object(objectName)//合并后的文件的objectname
                .sources(sources)//指定源文件
                .build();
        //===========合并文件============
        //报错size 1048576 must be greater than 5242880,minio默认的分块文件大小为5M
        try {
            minioClient.composeObject(composeObjectArgs);
        } catch (Exception e) {
            e.printStackTrace();
            log.error("合并文件出错,bucket:{},objectName:{},错误信息:{}",bucketName,objectName,e.getMessage());
            return Result.error("合并文件异常");
        }
        //===========校验合并后的和源文件是否一致,视频上传才成功===========
        //先下载合并后的文件
        File file = downloadFileFromMinIO(bucketName, objectName);
        try(FileInputStream fileInputStream = new FileInputStream(file)){
            //计算合并后文件的md5
            String mergeFile_md5 = DigestUtils.md5Hex(fileInputStream);
            //比较原始md5和合并后文件的md5
            if(!fileMd5.equals(mergeFile_md5)){
                log.error("校验合并文件md5值不一致,原始文件:{},合并文件:{}",fileMd5,mergeFile_md5);
                return Result.error("文件校验失败");
            }
        }catch (Exception e) {
            return Result.error("文件校验失败");
        }
        //==============将文件信息入库============
//        在做业务时要将得到的路径存入数据库
        //==========清理分块文件=========
        clearChunkFiles(chunkFileFolderPath,chunkTotal);
        return Result.success(true);
    }
    /**
     * 清除分块文件
     * @param chunkFileFolderPath 分块文件路径
     * @param chunkTotal 分块文件总数
     */
    private void clearChunkFiles(String chunkFileFolderPath,int chunkTotal){
        Iterable<DeleteObject> objects =  Stream.iterate(0, i -> ++i).limit(chunkTotal).map(i -> new DeleteObject(chunkFileFolderPath+ i)).collect(Collectors.toList());;
        RemoveObjectsArgs removeObjectsArgs = RemoveObjectsArgs.builder().bucket(bucketName).objects(objects).build();
        Iterable<io.minio.Result<DeleteError>> results = minioClient.removeObjects(removeObjectsArgs);
        //要想真正删除
        results.forEach(f->{
            try {
                DeleteError deleteError = f.get();
            } catch (Exception e) {
                e.printStackTrace();
            }
        });
    }


相关文章
|
19天前
|
JavaScript 前端开发 Java
springboot整合minio+vue实现大文件分片上传,断点续传(复制可用,包含minio工具类)
springboot整合minio+vue实现大文件分片上传,断点续传(复制可用,包含minio工具类)
650 0
|
19天前
|
Java Docker Windows
spring boot整合Minio
spring boot整合Minio
80 0
|
19天前
|
druid JavaScript Java
SpringBoot+Vue.js实现大文件分片上传、断点续传与极速秒传
SpringBoot+Vue.js实现大文件分片上传、断点续传与极速秒传
144 0
|
19天前
|
存储 Java 大数据
Springboot整合Minio实现文件上传和下载
Minio是一个灵活、高性能、开源的对象存储解决方案,适用于各种存储需求,并可以与云计算、容器化、大数据和应用程序集成。它为用户提供了自主控制和可扩展性,使其成为一个强大的存储解决方案。
267 0
|
19天前
|
Java Linux 开发工具
MinIO【部署 01】MinIO安装及SpringBoot集成简单测试
MinIO【部署 01】MinIO安装及SpringBoot集成简单测试
163 0
|
19天前
|
Apache
springboot+camel对接minio上传下载
springboot+camel对接minio上传下载
46 0
|
2天前
|
JavaScript Java 测试技术
基于SpringBoot+Vue+uniapp的漫画阅读系统的详细设计和实现(源码+lw+部署文档+讲解等)
基于SpringBoot+Vue+uniapp的漫画阅读系统的详细设计和实现(源码+lw+部署文档+讲解等)
|
2天前
|
JavaScript Java 测试技术
基于SpringBoot+Vue+uniapp的快递信息管理系统的详细设计和实现(源码+lw+部署文档+讲解等)
基于SpringBoot+Vue+uniapp的快递信息管理系统的详细设计和实现(源码+lw+部署文档+讲解等)
|
2天前
|
JavaScript Java 测试技术
基于SpringBoot+Vue+uniapp的高校听课评价系统的详细设计和实现(源码+lw+部署文档+讲解等)
基于SpringBoot+Vue+uniapp的高校听课评价系统的详细设计和实现(源码+lw+部署文档+讲解等)
|
2天前
|
JavaScript Java 测试技术
基于SpringBoot+Vue+uniapp的通讯录管理系统的详细设计和实现(源码+lw+部署文档+讲解等)
基于SpringBoot+Vue+uniapp的通讯录管理系统的详细设计和实现(源码+lw+部署文档+讲解等)