MinIO

一、MinIO

(上传文件,下载文件)

MinlO是一个基于Apache License v2.0开源协议的对象存储服务。它兼容亚马逊S3云存储服务接口,非常适合于存储大容量非结构化的数据。例如图片、视频、日志文件、备份数据和容器/虚拟机镜像等,而一个对象文件可以是任意大小,从几kb到最大5T不等。MinlO是一个非常轻量的服务 可以很简单的和其他应用的结合,类似NodeJS, Redis或者MySQL。

MinIO官网:MinIO | High Performance, Kubernetes Native Object Storage MinIO官方文档:

1、MinIO概述

1.1MinIO的优点

●部署简单:一个single二进制文件即是一切,还可以支持各种平台。

●minio支持海量存储,可按2one打展(原zone不受任何影响),支持单个对象最大5TB;

兼容Amazon S3接口,充分考虑开发人员的需求和体验;

●低冗余且磁盘损坏高容忍,标准且最高的数据冗余系数为2(即存储一个1 M的数据对象,实际占用磁盘空间为2M)。但在任意n/2块disk损坏的情况下依然可以读出数据(n为一个纠删码集合(Erasure Coding Set)中的disk数量)。并且这种损坏恢复是基于单个对象的,而不是基于整个存储卷的。

●读写性能优异

1.2、MinIO的基础概念

● Object: 存储到Minio的基本对象,如文件、字节流,Anything..

● Bucket:用来存储Object的逻辑空间。每个Bucket之间的数据是相互隔离的。对于客户端而言,就相当于一个存放文件的顶层文件夹。

● Drive: 即存储数据的磁盘,在MinIO启动时,以参数的方式传入。Minio 中所有的对象数据都会存储在Drive里。

● Set:即一组Drive的集合,分布式部署根据集群规模自动划分一 个或多个Set, 每个Set中的Drive分布在不同位置。一个对象存储在一个Set 上。(For example: {1..44} is divided into 4 sets each of size 16.)

● 一个对象存储在一 个Set上

● 一个集群划分为多个Set

● 一个Set包含的Drive数显是固定的,默认由系统根据集群规模自动计算得出

● 一个SET中的Drive尽可能分布在不同的节点上

1.3纠删码EC (Erasure Code)

MinIO使用纠删码机制来保证高可靠性,使用highwayhash来处理数据损坏( Bit Rot Protection)。关于纠删码,简单来说就是可以通过数学计算,把丢失的数据进行还原,它可以将n份原始数据,增加m份数据,并能通过n+m份中的任意n份数据,还原为原始数据。

即如果有任意小于等于m份的数据失效,仍然能通过剩下的数据还原出来。

1.4存储形式

文件对象上传到MinlO ,会在对应的数据存储磁盘中,以Bucket名称为目录,文件名称为下一级目录,文件名下是xl.meta,通过奇偶的形式存储 编码数据块及检验块和元数据文件。

如:

有data01,data02,data03,data04 四块盘

其中奇数盘:data01和data03中存储的是编码数据块及检验块(EC码)

偶数盘:data02和data04 存储的是元数据文件

1.5存储方案

2、windows系统部署MinIO

访问官网:MinIO Object Storage for Kubernetes — MinIO Object Storage for Kubernetes

进入官网之后点击右上角的DownLoad 进入下载页面 可以选择对应系统的安装包,我们下载windows版本的即可

windows版本下载之后是只有minio.exe文件,我们需要创建一个data文件,然后在打开cmd进入到minio.exe所在的文件夹中 执行

minio server ./data

执行完毕之后就是这样的 我们现在就可以访问自己电脑上的MinIO了

地址: http://127.0.0.1:9000

自习看之前的窗口 上面是有账号和密码的

RootUser: minioadmin

RootPass: minioadmin

3、Java整合MinIO

引入依赖:

<!-- MinIO -->
<dependency>
    <groupId>io.minio</groupId>
    <artifactId>minio</artifactId>
    <version>8.4.3</version>
</dependency>
<!-- okHttp:连接MinIO服务器(MinIO官方使用) -->
<dependency>
    <groupId>com.squareup.okhttp3</groupId>
    <artifactId>okhttp</artifactId>
    <version>4.9.0</version>
</dependency>

官方API文档:Java Client API Reference — MinIO Object Storage for Linux

书写测试类:

/**
 * @Description:测试MinIO
 * @Author:DW
 * @Date:2023/10/9 16:37
 */
@SpringBootTest
public class MinIOTest {
​
    @Test
    void test1() throws ServerException, InsufficientDataException, ErrorResponseException, IOException, NoSuchAlgorithmException, InvalidKeyException, InvalidResponseException, XmlParserException, InternalException {
        // 创建MinIO客户端
        MinioClient client = MinioClient.builder()
                .endpoint("http://localhost:9000")
                .credentials("minioadmin", "minioadmin")
                .build();
​
        // 判断要上传到的bucket是否存在,若不存在则创建
        String bucketName = "test";
        boolean found = client.bucketExists(BucketExistsArgs.builder().bucket(bucketName).build());
        if (!found){
            client.makeBucket(MakeBucketArgs.builder().bucket(bucketName).build());
        }else{
            System.out.println("【警告】名为" +bucketName+ "的bucket已经存在!!!");
        }
​
        // 判断桶中的文件夹是否存在
//        String dirName = "file/pic/";
//        client.putObject(PutObjectArgs.builder()
//                .bucket(bucketName)
//                .object(dirName)
//                .stream(new ByteArrayInputStream(new byte[] {}), 0, -1)
//                .build());
//        System.out.println("创建文件夹成功~~~");
​
        // 上传文件
        client.uploadObject(UploadObjectArgs.builder()
                .bucket(bucketName)  // 指定上传到哪个桶
                .object("file/pic/test3.jpg")  // 指定上传之后的文件名(可以写携带路径,此时MinIO会根据路径自动创建文件夹)
                .filename("C:\\Users\\13237\\Pictures\\Saved Pictures\\image (3).jpg")  // 被上传文件的路径
                .build());
​
        System.out.println("上传成功~~~");
    }
​
    @Test
    void test2() throws ServerException, InsufficientDataException, ErrorResponseException, IOException, NoSuchAlgorithmException, InvalidKeyException, InvalidResponseException, XmlParserException, InternalException {
        // 创建MinIO客户端
        MinioClient client = MinioClient.builder()
                .endpoint("http://localhost:9000")
                .credentials("minioadmin", "minioadmin")
                .build();
​
        // 下载文件
        client.downloadObject(DownloadObjectArgs.builder()
                        .bucket("test")
                        .object("file/pic/test3.jpg")
                        .filename("C:\\Users\\13237\\Desktop\\test3.jpg")
                        .build());
    }
​
​
}

minio的文件上传与删除

三. MinIO文件上传、删除

1. 引入依赖

        <!-- minio -->
        <dependency>
            <groupId>io.minio</groupId>
            <artifactId>minio</artifactId>
            <version>8.4.3</version>
        </dependency>
        <!-- okhttp,用于连接minio -->
        <dependency>
            <groupId>com.squareup.okhttp3</groupId>
            <artifactId>okhttp</artifactId>
            <version>4.9.0</version>
        </dependency>

2. 配置文件的编写

# 自定义minio的配置
minio:
  url: http://localhost:9000
  accessKey: minioadmin
  secretKey: minioadmin
​
# 文件上传的配置
shop-logo:
  bucketName: shop-logo

2. 配置类的编写

在base包中创建一个配置类

@Configuration
public class MinIOConfig {
​
    @Value("${minio.url}")
    private String minioUrl;
​
    @Value("${minio.accessKey}")
    private String accessKey;
​
    @Value("${minio.secretKey}")
    private String secretKey;
​
    @Bean
    public MinioClient minioClient(){
        return MinioClient.builder()
                .endpoint(minioUrl)  // MinIO服务的URL
                .credentials(accessKey, secretKey)
                .build();
    }
​
}

3、MinIO的工具类

在base包的util子包中创建一个工具类

public class MinIOUtil {
​
    /**
     * 判断桶是否存在
     * @param minioClient
     * @param bucketName
     * @return
     */
    @SneakyThrows  // 来自于lombok,用于在方法上自动生成异常声明(throws)
    public static boolean bucketExists(MinioClient minioClient, String bucketName) {
        return minioClient.bucketExists(BucketExistsArgs.builder().bucket(bucketName).build());
    }
​
    /**
     * 先执行判断,若桶不存在则创建
     * @param minioClient
     * @param bucketName
     */
    @SneakyThrows
    public static void createBucketByCondition(MinioClient minioClient, String bucketName){
        // 判断桶是否存在
        boolean result = bucketExists(minioClient, bucketName);
        if (!result){
            minioClient.makeBucket(MakeBucketArgs.builder().bucket(bucketName).build());
        }else{
            System.out.println("名为:" + bucketName +" 的桶已存在!!!");
        }
​
    }
​
    /**
     * 通过MultipartFile的IO流上传文件到MinIO
     * @param multipart
     * @param fileName
     * @param minioClient
     * @param bucketName
     */
    public static boolean uploadFile(MultipartFile multipart, String fileName,
                                  MinioClient minioClient, String bucketName){
        try {
            minioClient.putObject(PutObjectArgs.builder()
                    .bucket(bucketName)
                    .object(fileName)
                    .stream(multipart.getInputStream(), multipart.getSize(), -1)
                    .contentType(multipart.getContentType())
                    .build());
            return true;
        }catch (Exception e){
            e.printStackTrace();
            return false;
        }
    }
​
    /**
     * 删除MinIO中的文件
     * @param fileName
     * @param minioClient
     * @param bucketName
     * @return
     */
    public static boolean deleteFile(String fileName, MinioClient minioClient, String bucketName){
        try {
            minioClient.removeObject(RemoveObjectArgs.builder()
                    .bucket(bucketName)
                    .object(fileName)
                    .build());
            return true;
        }catch (Exception e){
            e.printStackTrace();
            return false;
        }
    }
​
}

4. 上传、删除接口

在base包中创建一个controller子包,并在该包中创建MinIOController

@RestController
@RequestMapping("/minio")
public class MinIOController {
​
    @Resource
    MinioClient minioClient;
​
    @Value("${shop-logo.bucketName}")
    private String bucketName;
​
    @PostMapping
    public AjaxResult upload(MultipartFile file){
        // 有条件地创建桶
        MinIOUtil.createBucketByCondition(minioClient, bucketName);
        String fileName = UUID.randomUUID() + "_" +file.getOriginalFilename();
        boolean result = MinIOUtil.uploadFile(file, fileName, minioClient, bucketName);
        if (result){
            // 上传成功则响应文件名给前端
            return AjaxResult.me().setSuccess(true).setMessage(fileName);
        }
        return AjaxResult.me().setSuccess(false).setMessage("上传失败!!!");
    }
​
    @DeleteMapping
    public AjaxResult delete(String fileName){
        boolean result = MinIOUtil.deleteFile(fileName, minioClient, bucketName);
        if(result){
            return AjaxResult.me().setSuccess(true).setMessage("删除成功!!!");
        }
        return AjaxResult.me().setSuccess(false).setMessage("删除失败!!!");
    }
​
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值