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();
            }
        });
    }


相关文章
|
24天前
|
XML Java API
SpringBoot 整合 Minio
本文介绍了如何在服务器上安装并配置Minio服务,包括Minio的依赖、配置类以及基本操作。首先,通过Maven添加Minio依赖;接着,在`yml`文件中配置Minio的连接信息;然后,创建`MinIoClientConfig`类将MinioClient注入到Spring容器中;最后,定义`OSSFileService`接口及其实现类`OssFileServiceImpl`,实现文件上传、获取文件URL、临时访问URL和删除文件等操作。
|
24天前
|
XML Java Kotlin
springboot + minio + kkfile实现文件预览
本文介绍了如何在容器中安装和启动kkfileviewer,并通过Spring Boot集成MinIO实现文件上传与预览功能。首先,通过下载kkfileviewer源码并构建Docker镜像来部署文件预览服务。接着,在Spring Boot项目中添加MinIO依赖,配置MinIO客户端,并实现文件上传与获取预览链接的接口。最后,通过测试验证文件上传和预览功能的正确性。
springboot + minio + kkfile实现文件预览
|
13天前
|
存储 前端开发 JavaScript
|
13天前
|
存储 Java API
|
1月前
|
存储 前端开发 Java
springboot整合最新版minio和minio的安装(完整教程,新人必看)
本文详细介绍了如何使用Docker安装配置最新版的MinIO,并展示了如何在Spring Boot应用中整合MinIO以及如何通过前端进行文件上传测试。
169 3
springboot整合最新版minio和minio的安装(完整教程,新人必看)
|
1月前
|
存储 前端开发 Java
Spring Boot 集成 MinIO 与 KKFile 实现文件预览功能
本文详细介绍如何在Spring Boot项目中集成MinIO对象存储系统与KKFileView文件预览工具,实现文件上传及在线预览功能。首先搭建MinIO服务器,并在Spring Boot中配置MinIO SDK进行文件管理;接着通过KKFileView提供文件预览服务,最终实现文档管理系统的高效文件处理能力。
262 11
|
3月前
|
存储 Java API
SpringBoot + MinIO 实现文件切片极速上传技术
【8月更文挑战第19天】在现代互联网应用中,文件上传是一个常见且重要的功能。然而,随着文件体积的增大,传统的文件上传方式往往面临效率低下、耗时过长等问题。为了提升大文件上传的速度和效率,我们可以采用文件切片上传技术,并结合SpringBoot和MinIO来实现这一功能。
218 0
|
5月前
|
前端开发 安全 Java
实现Spring Boot中的文件分片上传通常涉及到以下几个步骤和考虑的关键点
实现Spring Boot中的文件分片上传通常涉及到以下几个步骤和考虑的关键点
313 2
|
5月前
|
存储 开发框架 Java
SpringBoot整合Minio文件存储
该文档介绍了如何在公司开发框架中集成Minio以满足附件存储需求。由于规定附件服务器需与应用服务器分离且不使用云存储,Minio被选为解决方案。步骤包括:下载Minio部署包,创建配置文件(如`minio-service.xml`和`run.bat`),设置存储路径和访问凭据,安装服务并启动。之后,通过配置POM和YML文件以整合到项目中。此外,还提供了Minio工具类的初始化、上传、下载和删除文件的Java代码示例。
54 0
|
5月前
|
Java
springboot集成MinIO
springboot集成MinIO