首页 > 其他分享 >MinIO-对象存储简单使用

MinIO-对象存储简单使用

时间:2023-07-01 15:44:20浏览次数:52  
标签:存储 return MinIO 对象 bucket bucketName import public minio

MinIO

1. 基础概念

  • Object:存储到minio的基本对象,如文件,字节流,Anything...
  • Bucket:用来存储Object的逻辑空间。每个Bucket之间的数据是相互隔离的。对于客户端而言,就相当于一个存放文件的顶层文件夹。
  • Driver:即存储数据的磁盘,在minio启动时,以参数的方式传入。MinIO中所有的对象都会存储在Drive里。
  • Set:即一组Drive的集合,分布式部署根据集群规模自动划分一个或者set,每个set中的drive分布在不同的位置。一个对象存储在一个Set上。
    • 一个对象存储在一个Set上
    • 一个集群划分为多个set
    • 一个Set包含的Drive数量是固定的,默认由系统根据集群规模自动计算得出
    • 一个Set中的Drive尽可能分布在不同的节点上

2. 纠删码 EC(Erasure Code)

MinIO使用纠删码机制来保证高可靠性,使用highwayhash 来处理数据损坏 (2 Protection)。纠删码,可以通过数学计算,把丢失的数据进行还原,它可以将n份原始数据,增加m份数据,并能通过n+m份中的任意n份数据,还原为原始数据。即如果有任意小于等于m份的数据失效,仍能通过剩下的数据还原出来。

3. 单机部署

中文文档的docker部署有问题,没有暴露控制台的端口。

单机部署的命令

基于centos7的部署

# 下载
wget https://dl.min.io/server/minio/release/linux-amd64/archive/minio-20230616024106.0.0.x86_64.rpm -O minio.rpm
sudo dnf install minio.rpm
# 指定 控制台的root用户名和密码
export MINIO_ROOT_USER=admin123
export MINIO_ROOT_PASSWORD=admin123
# 指定 控制台暴露的端口,默认使用动态的端口,并指定数据存放的目录
./minio server --console-address ":50000" /data/minio-data
# 如果上述命令运行成功,可以通过控制台端口50000访问minio后台,证明运行时没问题的,就停掉。然后用下面的命令后台运行minio
nohup  ./minio server --console-address ":50000" /data/minio-data &

image-20230618191623676

image-20230618191652757

image-20230618191551966

控制台上传一个文件可以在服务器对应的目录中找到文件,服务正常运行。

基于docker的部署

docker 部署命令

docker pull docker://minio/minio

### 新版
docker run --name minio \
-p 9000:9000 \
-p 9999:9999 \
-d --restart=always \
-e "MINIO_ROOT_USER=admin123" \
-e "MINIO_ROOT_PASSWORD=admin123" \
-v /home/smy/minio-data/data:/data \
-v /home/smy/minio-data/config:/root/.minio \
minio/minio server /data \
--console-address '0.0.0.0:9999'

4. SpringBoot整合minio

遇到的问题

image-20230619153814425

解决方法:

修改minio的依赖的okhttp的依赖版本

        <!--minio-->
        <dependency>
            <groupId>io.minio</groupId>
            <artifactId>minio</artifactId>
            <version>8.2.1</version>
            <exclusions>
                <exclusion>
                    <groupId>com.squareup.okhttp3</groupId>
                    <artifactId>okhttp</artifactId>
                </exclusion>
                <exclusion>
                    <groupId>org.jetbrains.kotlin</groupId>
                    <artifactId>kotlin-stdlib</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
        <dependency>
            <groupId>com.squareup.okhttp3</groupId>
            <artifactId>okhttp</artifactId>
            <version>3.14.9</version>
        </dependency>
        <dependency>
            <groupId>org.jetbrains.kotlin</groupId>
            <artifactId>kotlin-stdlib</artifactId>
            <version>1.3.70</version>
        </dependency>

https://juejin.cn/post/7209110611858309179

5. JAVA API 操作 MinIO

官方文档

主要包括桶操作和文件操作:

  • 客户端的创建
  • 桶 增删改查
  • 文件 上传 下载 删除(过期删除)

image-20230621213958331

minio上传的大小限制,分片上传最小5MB,最大5GB;整个上传最大5TB。并且当不提供objectSize的时候,必须提供partSize(适合上传文件大小未知的场景)。

image-20230621223113936

putObject 上传文件后的返回对象

6. 工具类

image-20230701152015912

配置类

package org.example.config;

/**
 * @author myS
 * @description: MinioConfig
 * @date 2023/6/21 17:21
 */
public class MinioConfig {
    // 端点  单节点
    public static String END_POINT = "http://192.168.1.244:9000";
    // accessKey
    public static String ACCESS_KEY = "admin123";
    // secretKey
    public static String SECRET_KEY = "admin123";
    // bucketName 默认操作的bucket
    public static String BUCKET_NAME = "default";
}

工具类

结合实际业务做拓展

package org.example.utils;

import io.minio.*;
import io.minio.messages.*;
import org.example.config.MinioConfig;

import javax.annotation.Nonnull;
import java.io.InputStream;
import java.time.ZonedDateTime;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;

/**
 * @author myS
 * @description: MinioUtils
 * @date 2023/6/21 17:20
 */
public class MinioUtils {
    public static MinioClient minioClient = null;

    static {
        minioClient = MinioClient.builder()
                .endpoint(MinioConfig.END_POINT)
                .credentials(MinioConfig.ACCESS_KEY, MinioConfig.SECRET_KEY)
                .build();
    }

    // 1 桶操作

    /**
     * 1 根据 bucketName 判断 bucket 是否存在
     * @param bucketName
     * @return
     */
    public static boolean bucketExists(@Nonnull String bucketName) {
        try {
            return minioClient.bucketExists(BucketExistsArgs.builder().bucket(bucketName).build());
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    /**
     * 2 创建bucket, 使用时不需要提前判断 bucket 是否存在
     * @param bucketName
     * @return
     */
    public static boolean makeBucket(@Nonnull String bucketName) {
        try {
            // 当bucket不存在的时候,创建这个bucket
            if (bucketExists(bucketName)) {
                minioClient.makeBucket(MakeBucketArgs.builder()
                        .bucket(bucketName)
                        .build());
            }
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    /**
     * 3 根据bucketName删除一个bucket
     * @param bucketName
     * @return
     */
    public static boolean removeBucket(@Nonnull String bucketName) {
        try {
            minioClient.removeBucket(RemoveBucketArgs.builder()
                    .bucket(bucketName)
                    .build());
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    /**
     * 4 获取所有的 bucket, 使用时需要判断返回值是否为null,再进行后续操作
     * @return
     */
    public static List<Bucket> getAllBuckets() {
        try {
            List<Bucket> buckets = minioClient.listBuckets();
            return buckets;
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    /**
     * 5 设置 bucket 的声明周期,设置对象过期时间
     * @param bucketName 指定bucket,默认是对指定的这一个桶生效
     * @param expiredDays 过期时间 单位:天
     * @return
     */
    public static boolean setBucketLifecycle (@Nonnull String bucketName, @Nonnull Integer expiredDays) {
        // 创建一个带过期时间规则的配置config
        List<LifecycleRule> rules = new LinkedList<>();
        rules.add(
                new LifecycleRule(
                        Status.ENABLED,
                        null,
                        new Expiration((ZonedDateTime) null, expiredDays, null),
                        new RuleFilter("search"), // bucket下一级的目录 
                        "expiredRule_1",
                        null,
                        null,
                        null));
        LifecycleConfiguration config = new LifecycleConfiguration(rules);

        // 根据 config的配置,创建一个名称为 my-bucketname 的 bucket
        try {
            minioClient.setBucketLifecycle(
                    SetBucketLifecycleArgs.builder().bucket(bucketName).config(config).build());
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    // 二 文件操作

    /**
     * 上传文件并返回是否上传成功
     * @param bucketName
     * @param inputStream 待上传文件的输入流
     * @return
     */
    public static boolean upload (@Nonnull InputStream inputStream, @Nonnull String bucketName, @Nonnull String objectName) {
        try {
            ObjectWriteResponse objectWriteResponse = minioClient.putObject(
                    PutObjectArgs.builder()
                            .bucket(bucketName)
                            .stream(inputStream, -1, 1024 * 1024 * 10L) // 分片上传 10M
                            .object(objectName)
                            .build());
            System.out.println(objectWriteResponse.region());
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }

    }

    /**
     * 根据bucket和objectName返回一个minio中的对象的输入流
     * 因为可能为null,所以使用前需要先判null,避免发生其他错误
     * @param bucketName
     * @param objectName
     * @return
     */
    public static InputStream download (@Nonnull String bucketName, @Nonnull String objectName) {
        try {
            return minioClient.getObject(GetObjectArgs.builder()
                    .bucket(bucketName)
                    .object(objectName)
                    .build());
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    /**
     * 删除指定bucket下的名为objectName的对象
     * @param bucketName
     * @param objectName
     * @return
     */
    public static boolean removeObject(@Nonnull String bucketName, @Nonnull String objectName) {
        try {
            minioClient.removeObject(RemoveObjectArgs.builder()
                            .bucket(bucketName)
                            .object(objectName)
                    .build());
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    /**
     * 获取 当前bucket下的所有对象(只会列出一层)
     * @param bucketName
     * @return
     */
    public static List<String> getAllObjects (@Nonnull String bucketName) {
        List<String> allObjects = new ArrayList<>();
        try{
            Iterable<Result<Item>> results = minioClient.listObjects(ListObjectsArgs.builder()
                    .bucket(bucketName)
                    .build());
            results.forEach(item -> {
                Item item1 = null;
                try {
                    item1 = item.get();
                } catch (Exception e) {
                    e.printStackTrace();
                    throw new RuntimeException(e);
                }
                allObjects.add(item1.objectName());
            });
        } catch (Exception e) {
            e.printStackTrace();
        }
        return allObjects;
    }

}

工具类测试类

package org.example;

import io.minio.MinioClient;
import io.minio.messages.Bucket;
import org.example.utils.MinioUtils;
import org.junit.Assert;
import org.junit.Test;

import java.io.*;
import java.nio.file.Files;
import java.util.List;
import java.util.Objects;
import java.util.stream.Stream;

/**
 * @author myS
 * @description: TODO
 * @date 2023/6/21 21:47
 */
public class MinioTest {

//    public static MinioClient minioClient = MinioUtils.minioClient;

    /**
     * 测试 getAllBuckets 只能列出最外层的bucket,里层嵌套的bucket不能列出
     * logs
     * my-bucketname
     * test
     */
    @Test
    public void testList () {
        List<Bucket> test = MinioUtils.getAllBuckets();
        test.forEach(item -> {
            System.out.println(item.name());
        });
    }

    /**
     * 因为 inputStream 无法获取到 源文件的名字,所以需要指定一个 objectName,
     * 这个参数如果以 / 开头,就会新建一层目录;
     * 如果不以 / 开头,就会直接在 bucketName 下上传文件
     * 如果文件名和目录名 重复,后面的会覆盖前面的,前面的会在删除后面的之后显示出来  ****
     * @throws FileNotFoundException
     */
    @Test
    public void testUpload () throws FileNotFoundException {
        File file = new File("C:\\Users\\10170\\Desktop\\desktop\\cnblog\\待整理.md");
        InputStream inputStream = new FileInputStream(file);
        // 上传的文件路径: test/hdhd
        boolean upload = MinioUtils.upload(inputStream,"test","/hdhd");
        System.out.println(upload);
        // 上传的文件路径: test/hdhd/待整理.md
        boolean upload1 = MinioUtils.upload(inputStream,"test","/hdhd/"+file.getName());
        System.out.println(upload1);
    }

    /**
     * 测试 minio 的下载函数
     * 函数返回一个输入流,表示从文件写入内存中,用完close释放
     * 服务器程序拿到这个输入流之后,可以通过网络返回给前端
     * @throws IOException
     */
    @Test
    public void testDownload () throws IOException {
        InputStream stream = MinioUtils.download("logs", "b50aa3fcb9fa4f64a4e295b7a996aa9a/events.json");
        // stream 判 null
        if (Objects.isNull(stream)) {
            System.out.println("文件流为null!!!!! 下载失败");
            return ;
        }

        // 读取流 并下载
        File targetFile = new File("events.json");
        FileOutputStream fileOutputStream = new FileOutputStream(targetFile);
        byte[] bytes = new byte[1024];
        int length;
        while ((length = stream.read(bytes)) > 0) {
            fileOutputStream.write(bytes, 0, length);
        }
        fileOutputStream.close();
        stream.close();
    }

    /**
     * 删除 minio 文件对象测试
     */
    @Test
    public void testRemove() {
        boolean result = MinioUtils.removeObject("test", "hdhd/待整理.md");
        Assert.assertTrue(result);
    }

    @Test
    public void getAllObjects(){
        List<String> test = MinioUtils.getAllObjects("logs");
        test.forEach(System.out::println);
    }

}

标签:存储,return,MinIO,对象,bucket,bucketName,import,public,minio
From: https://www.cnblogs.com/Sun-yuan/p/17519379.html

相关文章

  • js-遍历两个对象数组,属性值相等的一项合并属性并生成新数组
    operatData.value.seriesList=res.data.seriesList.reduce((accumulator,current)=>{constexisting=userOptionsColor.find(item=>item.name===current.name)if(existing){accumulator.push({...current,...existing})......
  • 存储过程
    创建createprocedure存储过程名称([参数列表])begin--sql语句end;调用call名称([参数]);查看--查询指定数据库的存储过程及状态信息select*frominformation_schema.ROUTINESwhereROUTINE_SCHEMA='数据库名';showcreateprocedure存储过程名称;--......
  • 图论:图的概念、存储和遍历 学习笔记
    图论图的概念从数据结构的角度看,图可以看作一个多对多的数据存储结构。而结合图论算法,图就可以成为很多问题的载体。图论是数据结构与算法结合的产物。OIWiki上给出的图相关概念比较全面,但是因为OI是民科各个地方的一些定义都不太一样,所以作大概了解即可。图的存储图的存......
  • python脚本实现将md文件中的图片替换为本地存储
    实现将md文件中的网络图片下载下来,保存到本地./typora-img/{filename}目录,并且会将md文件中的图片地址替换为本地地址#代码参考:https://blog.csdn.net/weixin_34090643/article/details/91435765importrequestsimportreimportosfromitertoolsimportchainimportfn......
  • 靳宇灵 | CHATGPT真的很强大,很快帮我解决了tp5对接腾讯cos存储的SDK,NB!!
    php请求腾讯云cos存储SDK报错ThrowableErrorinClient.phpline229致命错误:CalltoundefinedfunctionCos\region_map()这个错误的原因是您在使用腾讯云cos存储SDK时,调用了一个未定义的函数 Cos\region_map()。首先,您需要确保安装了腾讯云cos存储SDK。可以通过Composer进......
  • 面向对象编程Python:类、对象和继承
    面向对象编程(Object-OrientedProgramming,简称OOP)是一种常用的编程范式,它将数据和操作数据的函数封装在一起,以创建对象。Python是一种支持面向对象编程的高级编程语言,它提供了类(class)、对象(object)和继承(inheritance)等概念,使得代码更加模块化、可维护性更高。本文将介绍Python中的......
  • python类与对象
    在Python中,类是一种用于创建对象的蓝图或模板。它们定义了对象的属性和方法。对象是类的实例化,它们是具体的、实际存在的实体。要定义一个类,可以使用class关键字,后面跟着类的名称。类名称通常使用首字母大写的驼峰命名法。下面是一个简单的类的示例:classPerson:def__init__(......
  • minio的使用
    文章目录官网简介下载搭建修改用户名密码使用通过java调接口,,直接官网上面引入对应jar:集群模式,多磁盘官网minio官网https://min.io中文镜像网站:http://minio.org.cn/有时候中文镜像网站是404,所以下载走中文镜像网站,文档走官网好了.简介MinIO是一个基于ApacheLicensev2......
  • 面向对象编程与面向过程编程的区别
    一、面向对象编程(OOP,ObjectOrientedProgramming):不必关心对象的具体实现,只需要能够满足用户的需求即可。主要以类或者对象为组织代码的基本单元。对象的三个主要的特性:1、对象的行为:可以对对象施加哪些操作,或者是对对象施加哪些方法。2、......
  • 15.面向对象和super
    面向对象和super()类(Class):具有相同的属性和方法的对象的集合,即定义对象的模板对象(Object):类的实例化对象,有自己的属性和方法。类方法:使用装饰器@classmethod,传递类的属性和方法(不能传实例的属性和方法)类属性:类中的变量。类变量在整个实例化的对象中是公用的实例......