Bootstrap

java项目使用docker当中的minio

2.3 Minio使用

2.3.1 Minio介绍

官网:MinIO | 用于AI的S3 & Kubernetes原生对象存储

MinIO是一个开源的分布式对象存储服务器,支持S3协议并且可以在多节点上实现数据的高可用和容错。它采用Go语言开发,拥有轻量级、高性能、

易部署等特点,并且可以自由选择底层存储介质。

MinIO的主要特点包括:

1、高性能:MinIO基于GO语言编写,具有高速、轻量级、高并发等性能特点,还支持多线程和缓存等机制进行优化,可以快速地处理大规模数据。

2、可扩展性:MinIO采用分布式存储模式,支持水平扩展,通过增加节点数量来扩展存储容量和性能,支持自动数据迁移和负载均衡。

3、安全性:MinIO提供了多种安全策略,如访问控制列表(ACL)、服务端加密(SSE)、传输层安全性(TLS)等,可以保障数据安全和隐私。

4、兼容性:MinIO兼容AWS S3 API,还支持其他云服务提供商的API,比如GCP、Azure等,可以通过简单的配置实现互操作性。

5、简单易用:MinIO的部署和管理非常简单,只需要运行一个二进制包即可启动服务,同时提供了Web界面和命令行工具等方便的管理工具。

S3协议是Amazon Web Services (AWS) 提供的对象存储服务(Simple Storage Service)的API协议。它是一种 RESTful风格的Web服务接口,使

用HTTP/HTTPS协议进行通信,支持多种编程语言和操作系统,并实现了数据的可靠存储、高扩展性以及良好的可用性。

2.3.2 Minio安装

官网地址:MinIO对象存储 Container — MinIO中文文档 | MinIO Container中文文档

具体命令:

// 创建数据存储目录
mkdir -p ~/minio/data
​
// 创建minio
docker run \
   -p 9001:9000 \
   -p 9090:9090 \
   --name minio \
   -v ~/minio/data:/data \
   -e "MINIO_ROOT_USER=admin" \
   -e "MINIO_ROOT_PASSWORD=admin123456" \
   -d \
   quay.io/minio/minio server /data --console-address ":9090"

2.3.3 Minio入门

本章节会给大家介绍一下如何通过Java客户端操作Minio,可以参考官网地址。

官网地址:Java Quickstart Guide — MinIO Object Storage for Linux

具体步骤:

1、加入如下依赖

<!-- common-util模块中加入如下依赖 -->
<dependency>
    <groupId>io.minio</groupId>
    <artifactId>minio</artifactId>
    <version>8.5.2</version>
</dependency>

2、示例代码

public class FileUploadTest {
​
    public static void main(String[] args) throws Exception {
​
        // 创建一个Minio的客户端对象
        MinioClient minioClient = MinioClient.builder()
                        .endpoint("http://192.168.136.142:9001")
                        .credentials("admin", "admin123456")
                        .build();
​
        boolean found = minioClient.bucketExists(BucketExistsArgs.builder().bucket("spzx-bucket").build());
​
        // 如果不存在,那么此时就创建一个新的桶
        if (!found) {
            minioClient.makeBucket(MakeBucketArgs.builder().bucket("spzx-bucket").build());
        } else {  // 如果存在打印信息
            System.out.println("Bucket 'spzx-bucket' already exists.");
        }
​
        FileInputStream fis = new FileInputStream("D://images//1.jpg") ;
        PutObjectArgs putObjectArgs = PutObjectArgs.builder()
                .bucket("spzx-bucket")
                .stream(fis, fis.available(), -1)
                .object("1.jpg")
                .build();
        minioClient.putObject(putObjectArgs) ;
​
        // 构建fileUrl
        String fileUrl = "http://192.168.136.142:9001/spzx-bucket/1.jpg" ;
        System.out.println(fileUrl);
​
    }
​
}

注意:设置minio的中该桶的访问权限为public,如下所示:

image-20230515234445425

2.4 上传文件接口

2.4.1 FileUploadController

上传文件的表现层代码:

@RestController
@RequestMapping("/admin/system")
public class FileUploadController {
​
    @Autowired
    private FileUploadService fileUploadService ;
​
    @PostMapping(value = "/fileUpload")
    public Result<String> fileUploadService(@RequestParam(value = "file") MultipartFile multipartFile) {
        String fileUrl = fileUploadService.fileUpload(multipartFile) ;
        return Result.build(fileUrl , ResultCodeEnum.SUCCESS) ;
    }
​
}

2.4.2 FileUploadService

上传文件的业务层代码:

@Service
public class FileUploadServiceImpl implements FileUploadService {
​
    @Autowired
    private MinioProperties minioProperties ;
​
    @Override
    public String fileUpload(MultipartFile multipartFile) {
​
        try {
​
            // 创建一个Minio的客户端对象
            MinioClient minioClient = MinioClient.builder()
                    .endpoint(minioProperties.getEndpointUrl())
                    .credentials(minioProperties.getAccessKey(), minioProperties.getSecreKey())
                    .build();
​
            // 判断桶是否存在
            boolean found = minioClient.bucketExists(BucketExistsArgs.builder().bucket(minioProperties.getBucketName()).build());
            if (!found) {       // 如果不存在,那么此时就创建一个新的桶
                minioClient.makeBucket(MakeBucketArgs.builder().bucket(minioProperties.getBucketName()).build());
            } else {  // 如果存在打印信息
                System.out.println("Bucket 'spzx-bucket' already exists.");
            }
​
            // 设置存储对象名称
            String extFileName = FileNameUtils.getExtension(multipartFile.getOriginalFilename());
            String fileName = new SimpleDateFormat("yyyyMMdd")
                    .format(new Date()) + "/" + UUID.randomUUID().toString().replace("-" , "") + "." + extFileName;
​
            PutObjectArgs putObjectArgs = PutObjectArgs.builder()
                    .bucket(minioProperties.getBucketName())
                    .stream(multipartFile.getInputStream(), multipartFile.getSize(), -1)
                    .object(fileName)
                    .build();
            minioClient.putObject(putObjectArgs) ;
​
            return minioProperties.getEndpointUrl() + "/" + minioProperties.getBucketName() + "/" + fileName ;
​
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
​
    }
}

2.4.3 MinioProperties

将构建MinioClient所对应的参数定义到配置文件中,然后通过该实体类封装该配置文件中的内容。

@Data
@ConfigurationProperties(prefix="spzx.minio") //读取节点
public class MinioProperties {
​
    private String endpointUrl;
    private String accessKey;
    private String secreKey;
    private String bucketName;
​
}

2.4.4 配置文件内容

在配置文件中添加Minio的相关配置

# 自定义配置
spzx:
  minio:
    endpointUrl: http://192.168.136.142:9001
    accessKey: admin
    secreKey: admin123456
    bucketName: sph

通过postman进行测试。

当你已有桶并且配置了public后可以直接

package com.atguigu.spzx.manager.service.imp;

import cn.hutool.core.date.DateTime;
import com.atguigu.spzx.manager.service.FileUploadService;
import io.minio.MinioClient;
import io.minio.PutObjectArgs;
import io.minio.errors.*;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;

/**
 * @version: java version 1.8
 * @Author: Mr Orange
 * @description: 该类是文件上传服务的实现类,实现了 FileUploadService 接口中的文件上传方法
 * @date: 2025-02-06 13:31
 */
@Service // 使用 Spring 的 @Service 注解,将该类标记为服务层组件,以便 Spring 进行管理
public class FileUploadServiceImpl implements FileUploadService {

    /**
     * 实现文件上传的具体逻辑
     * @param multipartFile 从客户端接收到的上传文件对象
     * @return 上传后文件的访问 URL
     * @throws ServerException 服务器端异常
     * @throws InsufficientDataException 数据不足异常
     * @throws ErrorResponseException 错误响应异常
     * @throws IOException 输入输出异常
     * @throws NoSuchAlgorithmException 不支持的算法异常
     * @throws InvalidKeyException 无效密钥异常
     * @throws InvalidResponseException 无效响应异常
     * @throws XmlParserException XML 解析异常
     * @throws InternalException 内部异常
     */
    @Override
    public String fileUpload(MultipartFile multipartFile) throws ServerException, InsufficientDataException, ErrorResponseException, IOException, NoSuchAlgorithmException, InvalidKeyException, InvalidResponseException, XmlParserException, InternalException {
        // 1. 创建 MinIO 客户端
        // 使用 MinioClient 的构建器模式创建客户端实例
        // .endpoint("http://192.168.153.128:9002") 指定 MinIO 服务的端点地址
        // .credentials("admin", "admin123456") 指定访问 MinIO 服务所需的凭证(用户名和密码)
        MinioClient minioClient = MinioClient.builder()
                .endpoint("http://192.168.153.128:9002")
                .credentials("admin", "admin123456")
                .build();

        // 2. 处理上传文件的文件名
        // 获取上传文件的原始文件名,并在前面添加 "avatar/" 作为文件的存储目录
        String originalFilename ="avatar"+"/"+ multipartFile.getOriginalFilename();

        // 3. 构建上传文件所需的参数对象
        // 使用 PutObjectArgs 的构建器模式构建上传文件的参数
        // .bucket("spzx-1") 指定要上传到的 MinIO 存储桶名称
        // .stream(multipartFile.getInputStream(), multipartFile.getSize(), -1) 指定上传文件的输入流、文件大小,-1 表示使用默认的分块大小
        // .object(originalFilename) 指定上传后文件在存储桶中的对象名称
        PutObjectArgs putObjectArgs = PutObjectArgs.builder()
                .bucket("spzx-1")
                .stream(multipartFile.getInputStream(), multipartFile.getSize(), -1)
                .object(originalFilename)
                .build();

        // 4. 执行文件上传操作
        // 调用 MinioClient 的 putObject 方法将文件上传到 MinIO 存储桶中
        minioClient.putObject(putObjectArgs);

        // 5. 生成并返回上传后文件的访问 URL
        // 获取当前日期并格式化为 "/yyyy/MM/dd" 的字符串形式
        String timeStr = new DateTime().toString("/yyyy/MM/dd");
        // 构建文件的访问 URL,格式为 "http://192.168.153.128:9002/spzx-1/avatar/文件名"
        String url ="http://192.168.153.128:9002/"+"spzx-1"+"/"+originalFilename;

        return url;
    }
}

悦读

道可道,非常道;名可名,非常名。 无名,天地之始,有名,万物之母。 故常无欲,以观其妙,常有欲,以观其徼。 此两者,同出而异名,同谓之玄,玄之又玄,众妙之门。

;