使用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官方

发表评论

相关文章