使用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)导入相关的依赖

4.0.0org.qbbspringboot-minio1.0org.springframework.bootspring-boot-starter-parent2.3.7.RELEASEorg.springframework.bootspring-boot-starter-weborg.springframework.bootspring-boot-starter-testorg.projectlomboklombok1.18.24io.springfoxspringfox-swagger22.7.0io.springfoxspringfox-swagger-ui2.7.0io.miniominio8.3.0

(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.qztxs.com/archives/science/technology/8263

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023年1月26日 下午5:33
下一篇 2023年1月26日 下午5:39

相关推荐

  • sqlmap笔记

    0x00 安装 git clone https://github.com/sqlmapproject/sqlmap.git 0x01 基本用法 常用参数 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 -dbs       //列举数据库 --count -D “数据库”   //获取表中数据个数 --curr...

    技术 2022年6月2日
    1600
  • 帖子中心,1亿数据,架构如何设计?

    帖子中心,是互联网业务中,一类典型的“1对多”业务,即:一个用户能发布多个帖子,一个帖子只有一个发布者。   随着数据量的逐步增大,并发量的逐步增大,帖子中心这种“1对多”业务,架构应该如何设计,有哪些因素需要考虑,是本文将要系统性讨论的问题。 什么是x对x? 所谓的“1对1”,“1对多”,“多对多”,来自数据库设计中的“实体-关系”ER模型,用来描述实体之...

    2022年5月14日
    2100
  • hexo添加文章目录

    0x00 前言 有的文章比较长,翻页查阅比较麻烦,添加文章目录功能 0x01 添加文章目录   添加css样式 打开themesLandscape-xsourcecss_partialarticle.styl,添加下面代码 1 2 3 4 5 6 7 8 9 /* 新添加的 */ #container .show-toc-btn,#containe...

    技术 2022年6月2日
    7600
  • 如何在12个小时,搞定日志监控?

    日志监控,是每个公司必须解决的一个问题。创业型公司,如何用半天的时间,搞定一个可扩展,通用的日志监控框架,是今天要聊的话题。   什么是日志监控? 关于日志,不同公司,情况不同: (1)A类公司:没有日志; (2)B类公司:有日志,只有用户说系统挂了,或者有bug的时候,才会登录到系统看看日志,大部分日志打印得对心所欲,缺乏组织性和系统性; 画外音:很多时候...

    2022年5月15日
    1800
  • java面试字节跳动——字节码

    1.前言 先来个定义:Java字节码是一组可以由Java虚拟机(JVM)执行的高度优化的指令,它被记录在Class文件中,在虚拟机加载Class文件时执行。 说大白话就是,字节码是Java虚拟机能够看明白的可执行指令。 前面的文章中已经强调了很多次了,Class文件不等于字节码,为什么我要一直强调这个事情呢? 因为在绝大部分的中文资料和博客中,这两个东西都被...

    2022年5月18日
    4700

发表回复

您的电子邮箱地址不会被公开。 必填项已用*标注

联系我们

400-800-8888

在线咨询: QQ交谈

邮件:admin@example.com

工作时间:周一至周五,9:30-18:30,节假日休息

关注微信