SpringBoot整合minio分布式文件实操

2,290 阅读4分钟

携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第31天,点击查看活动详情


1.写在前面

在java web编程中,目前微服务体系的框架越来越流行了,随着服务的拆分,可能我们的项目的细粒度,会变得很细。

一般的项目,基本上都会涉及到文件的存储。对于文件的存储,这个在微服务的体系下,我们可以将文件抽取出一个独立的文件微服务。然后提供相应的api(上传,下载,删除)等......

对于独立的文件微服务,我们可以根据项目的需求,使用策略模式,整合多个文件服务器,例如:阿里云Ossfastdfsminio等。

今天我们主要讲的是minio:

MinIO是专门为海量数据存储、人工智能、大数据分析而设计的对象存储系统。据官方介绍,单个对象最大可达5TB。非常适合储海量图片、视频、日志文件、备份数据和容器/虚拟机镜像等

  1. 安装部署非常简单
  2. 操作简单,自带ui
  3. 性能优秀,可以达到每秒GB级别的读写速度
  4. 支持主流的云原生容器化部署
  5. 提供多语言SDK的支持
  6. 参考学习文档非常全面

既然minio有这么多优点,那我们来整合一下minio吧!

2.minio部署

学习文档:minio学习文档

githug地址:minio

java sdk文档:java sdk

docker 部署文档:docker部署minio

这里提供的文档是英文的,为什么这里列出中文的文档呢?

那是因为中文的文档,有些地址都是404,好像没有更新维护一样,所以这里只是列出英文的文档。

但是也建议大家看英文的文档,毕竟大部分的文档都是英文的。哈哈!!!

这里使用docker方式部署minio:

# 创建一个文件夹
mkdir -p ~/minio/data

# docker运行minio
docker run \
   -p 9000:9000 \
   -p 9090:9090 \
   --name minio \
   -v ~/minio/data:/data \
   -e "MINIO_ROOT_USER=ROOTNAME" \
   -e "MINIO_ROOT_PASSWORD=CHANGEME123" \
   quay.io/minio/minio server /data --console-address ":9090"

当前镜像版本:RELEASE.2022-08-26T19-53-15Z

image.png

上面的命令,有过docker基础的人应该都可以看得懂吧,没有的也没关系,我们一一说明一下:

-p:9000:9000 (hostPort:containerPort)表示映射的容器的9000端口到主机的9000端号。
--name minio 表示给当前容器一个名称为minio
-v ~/minio/data:/data 表示将容器的/data文件夹,挂载到主机的~/minio/data文件夹下面
-e "MINIO_ROOT_USER=ROOTNAME"  表示传递一个环境变量给到容器。
quay.io/minio/minio  表示镜像名称
server /data --console-address ":9090"  表示容器启动后需要执行的命令

MINIO_ROOT_USER、MINIO_ROOT_PASSWORD,为minio的账号密码,可以用来登录web ui客户端,也可以作为java sdk的accessKey、secretKey

--console-address ":9090",为web ui客户端的端口号

-p 9000:9000,为minio api的端口号

minio启动成功后,可以直接访问:http://localhost:9090 进入到web ui客户端

image.png

3.整合minio

3.1 pom.xml依赖

<!--加入minio的依赖-->
<dependency>
    <groupId>io.minio</groupId>
    <artifactId>minio</artifactId>
    <version>8.4.1</version>
    <exclusions>
        <exclusion>
            <artifactId>okhttp</artifactId>
            <groupId>com.squareup.okhttp3</groupId>
        </exclusion>
    </exclusions>
</dependency>
<dependency>
    <groupId>com.squareup.okhttp3</groupId>
    <artifactId>okhttp</artifactId>
    <version>4.9.3</version>
</dependency>

3.2 minio 配置

{
	"endpoint": "http://localhost:9000",
	"bucketName": "llsydn",
	"accessKey": "ROOTNAME",
	"secretKey": "CHANGEME123"
}

endpoint,就是minio api的ip+端口号,就是上面暴露的9000端口

accessKey,secretKey,就是上面的MINIO_ROOT_USER和MINIO_ROOT_PASSWORD

bucketName,表示桶名,我们可以理解为一个文件夹名称

3.3 minio客户端

/**
 * 构造minio客户端。
 *
 * @param sysFileStore
 * @return
 */
private MinioClient buildMinioClient(JSONObject sysFileStore) {
    //连接地址
    String endpoint = sysFileStore.getString("endpoint");
    //账号
    String accessKey = sysFileStore.getString("accessKey");
    //密码
    String secretKey = sysFileStore.getString("secretKey");

    MinioClient minioClient = MinioClient.builder()
            .endpoint(endpoint)
            .credentials(accessKey, secretKey)
            .build();
    return minioClient;
}

3.4 上传文件

@Override
public boolean createFile(String fileName, byte[] bytes) {
    try {
        String config = "刚才那段json配置";
        JSONObject sysFileStore = JSONObject.parseObject(config);
        String bucketName = sysFileStore.getString("bucketName");

        // 创建MinioClient实例
        MinioClient minioClient = buildMinioClient(sysFileStore);

        // 先判断bucketName桶是否存在,不存在,先创建桶
        BucketExistsArgs bucketExistsArgs = BucketExistsArgs.builder().bucket(bucketName).build();
        boolean flag = minioClient.bucketExists(bucketExistsArgs);
        if (!flag) {
            MakeBucketArgs makeBucketArgs = MakeBucketArgs.builder().bucket(bucketName).build();
            minioClient.makeBucket(makeBucketArgs);
        }

        //fileName:存储桶里的对象名称
        PutObjectArgs putObjectArgs = PutObjectArgs.builder().bucket(bucketName).object(fileName)
                .stream(new ByteArrayInputStream(bytes), bytes.length, -1).build();

        // 上传到minio
        minioClient.putObject(putObjectArgs);

    } catch (Exception e) {
        log.error("------MinioOperator.createFile is error :" + e.getMessage());
    }
}

3.5 下载文件

@Override
public void downFile(HttpServletResponse response, String path) {
    try {
        String config = "刚才那段json配置";
        
        JSONObject sysFileStore = JSONObject.parseObject(config);
        String bucketName = sysFileStore.getString("bucketName");

      
        // 创建minioClient实例。
        MinioClient minioClient = buildMinioClient(sysFileStore);
        
        //sysFile.getPath():存储桶里的对象名称
        GetObjectArgs objectArgs = GetObjectArgs.builder().bucket(bucketName).object(path).build();
        
        // 获取minio文件inputStream对象
        InputStream inputStream = minioClient.getObject(objectArgs);

        FileUtil.downLoad(inputStream, response);
    } catch (Exception e) {
        log.error("------MinioOperator.downFile is error :" + e.getMessage());
    }
}

3.6 删除文件

@Override
public int delFile(String path) {

    try {
        String config = "刚才那段json配置";
        
        JSONObject sysFileStore = JSONObject.parseObject(config);
        //存储桶名称
        String bucketName = sysFileStore.getString("bucketName");

        // 创建minioClient实例。
        MinioClient minioClient = buildMinioClient(sysFileStore);

        //path:存储桶里的对象名称
        minioClient.removeObject(RemoveObjectArgs.builder().bucket(bucketName).object(path).build());

    } catch (Exception ex) {
        log.error("------MinioOperator.delFile is error :" + e.getMessage());
    }
    return 0;
}

好了,以上就是SpringBoot整合minio分布式文件实操的分享了。

可能内容有点短,但都是干货喔!!!

个人理解,可能也不够全面,班门弄斧了。

如果觉得有收获的,帮忙点赞、评论、收藏一下呗!!!

image.png