使用MinIO搭建对象存储服务

1.MinIO是什么?

  • MinIO 是一款高性能、分布式的对象存储系统. 它是一款软件产品, 可以100%的运行在标准硬件。即X86等低成本机器也能够很好的运行MinIO。
  • MinIO与传统的存储和其他的对象存储不同的是:它一开始就针对性能要求更高的私有云标准进行软件架构设计。因为MinIO一开始就只为对象存储而设计。所以他采用了更易用的方式进行设计,它能实现对象存储所需要的全部功能,在性能上也更加强劲,它不会为了更多的业务功能而妥协,失去MinIO的易用性、高效性。 这样的结果所带来的好处是:它能够更简单的实现局有弹性伸缩能力的原生对象存储服务。
  • MinIO在传统对象存储用例(例如辅助存储,灾难恢复和归档)方面表现出色。同时,它在机器学习、大数据、私有云、混合云等方面的存储技术上也独树一帜。当然,也不排除数据分析、高性能应用负载、原生云的支持。

之前我使用的是阿里云OSS,想了解阿里云OSS的小伙伴参考SpringBoot整合阿里云OSS

2.我这里使用的是docker安装方式,使用的前提是小伙伴你已经安装好了一个docker了,关于docker的具体使用可以参考docker的具体使用

《使用MinIO搭建对象存储服务》

3.使用步骤

(1)下载镜像,下载可能有点慢大家等待一下或者配置一下阿里云镜像加速器

docker run -d -p 9000:9000 -p 9001:9001 --name minio -e MINIO_ACCESS_KEY=qbb -e MINIO_SECRET_KEY=startqbb -v /opt/minio/data:/data -v /opt/minio/config:/root/.minio minio/minio server /data --console-address ":9000" --address ":9001"

  • MINIO_ACCESS_KEY:指定的是”用户名”,可以这么理解,后面我们文件上传需要使用
  • MINIO_SECRET_KEY:指定的是”密码”,可以这么理解,后面我们文件上传需要使用

《使用MinIO搭建对象存储服务》

下载并运行完成

《使用MinIO搭建对象存储服务》

注意:
  • 有可能下载的过程中会出现如下图,minio容器并没有正常启动
    docker ps -a:查看所有容器
    《使用MinIO搭建对象存储服务》

  • 我们可以使用docker logs 容器ID(CONTAINERID)查看一下容器的日志
    《使用MinIO搭建对象存储服务》

  • 可以看出数data目录没有权限,执行如下命令在启动试试
    chmod 777 /opt/minio/data:设置目录权限为可读可写可执行
    docker start 容器ID:启动容器
    《使用MinIO搭建对象存储服务》

(2)我们先在浏览器访问一下http://192.168.137.72:9000/

《使用MinIO搭建对象存储服务》

(3)我们在minio中创建一个bucket

(4)接下来我们创建一个SpringBoot项目

《使用MinIO搭建对象存储服务》

(5)导入相关的依赖

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>org.qbb</groupId>
    <artifactId>springboot-minio</artifactId>
    <version>1.0</version>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.3.7.RELEASE</version>
    </parent>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
        </dependency>

        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.24</version>
        </dependency>

        <!--swagger-->
        <dependency>
            <groupId>io.springfox</groupId>
            <artifactId>springfox-swagger2</artifactId>
            <version>2.7.0</version>
        </dependency>
        <!--swagger ui-->
        <dependency>
            <groupId>io.springfox</groupId>
            <artifactId>springfox-swagger-ui</artifactId>
            <version>2.7.0</version>
        </dependency>

        <dependency>
            <groupId>io.minio</groupId>
            <artifactId>minio</artifactId>
            <version>8.3.0</version>
        </dependency>
    </dependencies>

</project>

(6)修改application.yml配置文件

server:
  port: 7200

spring:
  application:
    name: minio

app:
  minio:
    endpoint: http://192.168.137.72:9001
    accessKey: qbb
    secretKey: startqbb
    bucket: qbb

注意:9000是我们浏览器访问控制台的端口,而9001是SDK代码操作的端口

(7)主启动类

package com.qbb.minio;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

/**
 * @author QiuQiu&LL (个人博客:https://www.cnblogs.com/qbbit)
 * @version 1.0
 * @date 2022-05-20  15:45
 * @Description:
 */
@SpringBootApplication
public class MinioApplication {
    public static void main(String[] args) {
        SpringApplication.run(MinioApplication.class, args);
    }
}

(8)这里我配置一个swagger2方便测试,还配置了一个minio的配置类绑定配置文件信息,具体配置如下

package com.qbb.minio.config;

import com.google.common.base.Predicates;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import springfox.documentation.builders.ApiInfoBuilder;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.service.ApiInfo;
import springfox.documentation.service.Contact;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2;

/**
 * @author QiuQiu&LL (个人博客:https://www.cnblogs.com/qbbit)
 * @version 1.0
 * @date 2022-05-20  16:23
 * @Description:swagger配置类
 */
@Configuration
@EnableSwagger2
public class Swagger2Config {

    @Bean
    public Docket adminApiConfig() {
        return new Docket(DocumentationType.SWAGGER_2)
                .groupName("minioApi")
                .apiInfo(adminApiInfo())
                .select()
                //只显示admin路径下的页面
                .paths(Predicates.and(PathSelectors.regex("/minio/.*")))
                .build();
    }

    private ApiInfo adminApiInfo() {

        return new ApiInfoBuilder()
                .title("minio-API文档")
                .version("1.0")
                .contact(new Contact("QIUQIU&LL", "https://www.cnblogs.com/qbbit", "startqbb@163.com"))
                .build();
    }
}



package com.qbb.minio.config;

import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Configuration;

/**
 * @author QiuQiu&LL (个人博客:https://www.cnblogs.com/qbbit)
 * @version 1.0
 * @date 2022-05-20  18:57
 * @Description:
 */
@ConfigurationProperties(prefix = "app.minio")
@EnableConfigurationProperties
@Configuration
@Data
public class MinioConfig {

    private String endpoint;
    private String accessKey;
    private String secretKey;
    private String bucket;
}

(9)编写测试代码

package com.qbb.minio.controller;

import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

/**
 * @author QiuQiu&LL (个人博客:https://www.cnblogs.com/qbbit)
 * @version 1.0
 * @date 2022-05-20  16:23
 * @Description:
 */
@Api(tags = "minio文件管理")
@RestController
@RequestMapping("/minio")
public class FileController {

    @ApiOperation("测试程序")
    @GetMapping("/hello")
    public String hello() {
        return "hello";
    }

}

《使用MinIO搭建对象存储服务》

(10)接下来我们编写文件上传代码

package com.qbb.minio.controller;

import com.qbb.minio.config.MinioConfig;
import io.minio.MinioClient;
import io.minio.PutObjectOptions;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;

import java.io.InputStream;
import java.util.UUID;


/**
 * @author QiuQiu&LL (个人博客:https://www.cnblogs.com/qbbit)
 * @version 1.0
 * @date 2022-05-20  16:23
 * @Description:
 */
@Api(tags = "minio文件管理")
@RestController
@RequestMapping("/minio")
public class FileController {

    @Autowired
    private MinioConfig minioConfig;

    @ApiOperation("测试程序")
    @GetMapping("/hello")
    public String hello() {
        return "hello";
    }

    @ApiOperation("文件上传")
    @PostMapping("/fileUpload")
    public String fileUpload(MultipartFile file) {
        /**
         * 这里应该放在service层处理的,将上传的文件路径存入数据库,我就不这么麻烦了,直接返回给前端
         */
        String bucket = minioConfig.getBucket();
        String endpoint = minioConfig.getEndpoint();
        String accessKey = minioConfig.getAccessKey();
        String secretKey = minioConfig.getSecretKey();

        // 1.获取文件名
        String originalFilename = file.getOriginalFilename();

        // 2.修改文件名,防止上传重复文件名,导致文件覆盖
        String fileName = UUID.randomUUID().toString().replace("-", "") + "_" + originalFilename;
        // 文件流
        try (InputStream inputStream = file.getInputStream()) {
            // 3.使用MinIO服务的URL,端口,Access key和Secret key创建一个MinioClient对象
            MinioClient minioClient = new MinioClient(endpoint, accessKey, secretKey);

            // 4.检查存储桶是否已经存在
            boolean isExist = minioClient.bucketExists(bucket);
            if (isExist) {
                System.out.println("Bucket already exists");
            } else {
                // 不存在则创建一个名为bucket的存储桶,用于存储照片的zip文件。
                minioClient.makeBucket(bucket);
            }
            // 6.上传参数设置项
            PutObjectOptions options = new PutObjectOptions(inputStream.available(), -1);

            // 7.设置此次上传的文件的内容类型
            String contentType = file.getContentType();
            options.setContentType(contentType);

            // 8.上传
            minioClient.putObject(bucket, fileName, inputStream, options);

            // 9.访问路径
            String url = endpoint + "/" + bucket + "/" + fileName;
            return url;
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

}

(11)使用Swagger测试一下

《使用MinIO搭建对象存储服务》

(12)结果

  • swagger
    《使用MinIO搭建对象存储服务》

  • minio控制台
    《使用MinIO搭建对象存储服务》

(13)删除minio中的文件

 @ApiOperation("删除文件")
    @DeleteMapping("/remove")
    public boolean remove() {
        try {
            // 使用MinIO服务的URL,端口,Access key和Secret key创建一个MinioClient对象
            MinioClient minioClient = new MinioClient(minioConfig.getEndpoint(), minioConfig.getAccessKey(), minioConfig.getSecretKey());
            // 从bucket中删除文件(文件名)。
            minioClient.removeObject(minioConfig.getBucket(), "ed8aa56a8ec640d6a36a271ed4222605_xiaomi.png");
            System.out.println("successfully removed mybucket/myobject");
            return true;
        } catch (Exception e) {
            System.out.println("Error: " + e);
            return false;
        }
    }

(14)删除后的结果

  • swagger
    《使用MinIO搭建对象存储服务》

  • minio控制台
    《使用MinIO搭建对象存储服务》

(15)注意:我们配置完了,启动我们的项目可能会出现这么一个错误,说我们的请求时间与服务器时间相差太大

《使用MinIO搭建对象存储服务》

(16)解决办法,linux控制台

yum -y install ntp ntpdate:安装插件工具
hwclock --systohc:同步时间
docker restart minio镜像ID:重启镜像

至此SpringBoot整合Minio实现文件上传完成,更多详细的功能配置各位小伙伴可以参考minio官方

    原文作者:我也有梦想呀
    原文地址: https://www.cnblogs.com/qbbit/p/16291701.html
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞