spring boot 实现Minio分片上传的步骤

 更新时间:2023年10月14日 11:03:52   作者:过去日记  
分片上传,就是将所要上传的文件,按照一定的大小,将整个文件分隔成多个数据块来进行分别上传,上传完之后再由服务端对所有上传的文件进行汇总整合成原始的文件,本文给大家介绍spring boot 实现Minio分片上传的步骤,感兴趣的朋友跟随小编一起看看吧

应用场景

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

分片上传的场景

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

分片上传的步骤

检查文件的代码

在文件第一次上传时,上传文件的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();
            }
        });

    }

到此这篇关于spring boot 实现Minio分片上传的文章就介绍到这了,更多相关spring boot Minio分片上传内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • Spring中的自动装配机制详解

    Spring中的自动装配机制详解

    这篇文章主要介绍了Spring中的自动装配机制详解,自动装配就是会通过Spring的上下文为你找出相应依赖项的类,通俗的说就是Spring会在上下文中自动查找,并自动给Bean装配与其相关的属性,需要的朋友可以参考下
    2023-08-08
  • 详解Java中雪花算法的实现

    详解Java中雪花算法的实现

    雪花算法是一种分布式的id生成算法。原理是将long分成若干个区段分别管理。本文将利用Java简单的实现雪花算法,感兴趣的可以了解一下
    2022-12-12
  • SpringSecurity中PasswordEncoder的使用

    SpringSecurity中PasswordEncoder的使用

    密码存储和加密是非常重要的,本文主要介绍了SpringSecurity中PasswordEncoder的使用,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2025-01-01
  • JAVA实现基于皮尔逊相关系数的相似度详解

    JAVA实现基于皮尔逊相关系数的相似度详解

    这篇文章主要介绍了JAVA实现基于皮尔逊相关系数的相似度详解,具有一定参考价值,需要的朋友可以了解下。
    2017-11-11
  • Java用BigDecimal类解决Double类型精度丢失的问题

    Java用BigDecimal类解决Double类型精度丢失的问题

    这篇文章主要介绍了Java用BigDecimal类解决Double类型精度丢失的问题,帮助大家更好的理解和使用Java,感兴趣的朋友可以了解下
    2020-12-12
  • Spring的IOC解决程序耦合的实现

    Spring的IOC解决程序耦合的实现

    本文主要介绍了Spring的IOC解决程序耦合的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2024-07-07
  • Java超详细梳理IO流的使用方法上

    Java超详细梳理IO流的使用方法上

    流(Stream)是指一连串的数据(字符或字节),是以先进先出的方式发送信息的通道,数据源发送的数据经过这个通道到达目的地,按流向区分为输入流和输出流
    2022-04-04
  • Spring Boot拦截器和监听器实现对请求和响应处理实战

    Spring Boot拦截器和监听器实现对请求和响应处理实战

    这篇文章主要介绍了Spring Boot拦截器和监听器实现对请求和响应处理实战,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-06-06
  • java加载properties文件的六种方法总结

    java加载properties文件的六种方法总结

    这篇文章主要介绍了java加载properties文件的六种方法总结的相关资料,需要的朋友可以参考下
    2017-05-05
  • Java Class 解析器实现方法示例

    Java Class 解析器实现方法示例

    这篇文章主要通过对class文件的分析,介绍了Java Class 解析器实现方法示例,具有一定参考价值,需要的朋友可以了解下。
    2017-09-09

最新评论