Minio安装及整合SpringBoot

news2024/11/20 20:18:21
一. MinIO概述

官网地址:https://minio.org.cn

MinIO是一款基于Apache License v2.0开源协议的分布式文件系统(或者叫对象存储服务),可以做为云存储的解决方案用来保存海量的图片、视频、文档等。由于采用Golang实现,服务端可以工作在Windows、Linux、 OS X和FreeBSD上。配置简单,基本是复制可执行程序,单行命令就可以运行起来。

MinIO兼容亚马逊S3(Simple Storage Service,简单存储服务)云存储服务接口,非常适合于存储大容量非结构化的数据,例如图片、视频、日志文件、备份数据和容器/虚拟机镜像等,而且每个对象文件可以是任意大小,从几kb到最大5T不等。

 MinIO特点:

1. 高性能:作为高性能对象存储,在标准硬件条件下它能达到55GB/s的读、35GB/s的写速率;
2. 可扩容:不同MinIO集群可以组成联邦,并形成一个全局的命名空间,并跨越多个数据中心;
3. SDK支持: 基于Minio轻量的特点,它得到类似Java、Python或Go等语言的sdk支持;
4. 支持纠删码:MinIO使用纠删码、Checksum来防止硬件错误和静默数据污染。在最高冗余度配  置下,即使丢失1/2的磁盘也能恢复数据;

MinIO基本概念:

  • bucket(桶) :类似文件系统的目录(文件夹);
  • Object : 类似文件系统的文件;
  • Keys :类似文件名;
  • MINIO_ACCESS_KEY:访问key,类似账号;
  • MINIO_SECRET_KEY:秘钥,类似密码。
二. Dokcer安装Minio
2.1 创建文件夹

在home/docker/minio文件夹下创建两个文件夹,分别是data、config,用于挂载容器中的数据卷。

mkdir home/docker/minio/data
mkdir home/docker/minio/config
2.1 拉取镜像
docker pull minio/minio
2.3 启动容器
docker run -p 9000:9000 -p 9001:9001\
 --name minio \
 -d --restart=always \
 -e "MINIO_ROOT_USER=minio" \
 -e "MINIO_ROOT_PASSWORD=minio123" \
 -v /home/docker/minio/data:/data \
-v /home/docker/minio/config \
 minio/minio server \
 /data --console-address ":9001" -address ":9000"

参数说明

  • -p:MinIO 服务会暴露 9000 端口作为API端口,9001 端口为可视化管理页面端口
  • -v :挂载数据卷,将 minio 容器内存储的数据、配置文件映射到宿主机
  • -e MINIO_ROOT_USER:设置 root 用户名
  • -e MINIO_ROOT_PASSWORD:设置 root 的密码,长度至少 8 位
  • --console-address:指定可视化界面端口
  • -address:指定服务端口

记得开放安全组!

2.4 查看日志
docker logs minio容器id

通过以上命令查看 minio 日志,会输出以下内容:

我们可以通过日志中的Console地址来访问可视化界面。

三.访问Minio

登录成功后,可以创建桶

 此时在桶列表会会出现刚刚创建的桶,点击Manage,设置桶的访问策略,修改为 Public 公共策略,这样 minio 中的文件才能被外界访问

 并可以直接在桶中上传文件。

四. 整合Springboot完成文件上传
4.1创建springboot工程
4.2 导入相关依赖
<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter</artifactId>
    </dependency>

    <!-- 必须要导入OKhttp的依赖 -->
    <dependency>
        <groupId>com.squareup.okhttp3</groupId>
        <artifactId>okhttp</artifactId>
        <version>4.8.1</version>
    </dependency>

    <!-- https://mvnrepository.com/artifact/io.minio/minio -->
    <dependency>
        <groupId>io.minio</groupId>
        <artifactId>minio</artifactId>
        <version>8.5.7</version>
    </dependency>

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

    <!--lombok-->
    <dependency>
        <groupId>org.projectlombok</groupId>
        <artifactId>lombok</artifactId>
    </dependency>
</dependencies>
4.3 yaml中配置 Minio

在 yaml 中新增以下配置:

minio:
  accessKey: minio # 访问Key
  secretKey: minio123 # 密钥
  bucket: test 
  endpoint: http://xxx.x.x.x:9000 # ip:api端口
  readPath: http://xxx.x.x.x:9000 # ip:api端口
  servlet:
    multipart:
      # 单个上传文件的最大值是200mb
      max-file-size: 200MB
      # 单次请求的最大值
      max-request-size: 200MB
4.4 编写 MinIO属性配置类
@Data
@Component
@ConfigurationProperties(prefix = "minio")  //自动注入属性前缀为minio的配置
public class MinIOConfigProperties implements Serializable {

    private String accessKey; // 访问key
    private String secretKey; // 秘钥
    private String bucket;    // 桶
    private String endpoint;  // 地域节点
    private String readPath;  // 读取路径
}
4.5 编写MinIO配置类,注册MinioClient客户端Bean实例
@Configuration
public class MinIOConfig {

    @Autowired
    private MinIOConfigProperties minIOConfigProperties;

    // 注册MinIO实例
    @Bean
    public MinioClient buildMinioClient(){
        return MinioClient
                .builder()
                .credentials(minIOConfigProperties.getAccessKey(), minIOConfigProperties.getSecretKey())
                .endpoint(minIOConfigProperties.getEndpoint())
                .build();
    }
}
4.6 编写操作minio相关业务接口
public interface FileStorageService {

    /**
     * 上传图片文件
     *
     * @param prefix      文件前缀
     * @param filename    文件名
     * @param inputStream 文件流
     * @return 文件全路径
     */
    public String uploadImgFile(String prefix, String filename, InputStream inputStream);

    /**
     * 上传html文件
     *
     * @param prefix      文件前缀
     * @param filename    文件名
     * @param inputStream 文件流
     * @return 文件全路径
     */
    public String uploadHtmlFile(String prefix, String filename, InputStream inputStream);

    /**
     * 删除文件
     *
     * @param pathUrl 文件全路径
     */
    public void delete(String pathUrl);

    /**
     * 下载文件
     *
     * @param pathUrl 文件全路径
     * @return
     */
    public byte[] downLoadFile(String pathUrl);

}

业务接口实现类:

@Service
public class MinIOFileStorageService implements FileStorageService {
    @Autowired
    MinioClient minioClient;

    @Autowired
    MinIOConfigProperties minIOConfigProperties;

    final static String separator = "/"; //文件夹分隔符

    /**
     * 构建文件的绝对路径
     *
     * @param dirPath  文件路径
     * @param filename 文件名  yyyy/mm/dd/file.jpg
     * @return /test
     */
    public String builderFilePath(String dirPath, String filename) {
        StringBuilder stringBuilder = new StringBuilder(50);
        if (!StringUtils.isEmpty(dirPath)) {
            stringBuilder.append(dirPath).append(separator);
        }
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd");
        String todayStr = sdf.format(new Date());
        stringBuilder.append(todayStr).append(separator);
        stringBuilder.append(filename);
        return stringBuilder.toString();
    }

    /**
     * 上传图片文件
     *
     * @param prefix      文件前缀
     * @param filename    文件名
     * @param inputStream 文件流
     * @return 文件全路径
     */
    @Override
    public String uploadImgFile(String prefix, String filename, InputStream inputStream) {
        String filePath = builderFilePath(prefix, filename);
        try {
            PutObjectArgs putObjectArgs = PutObjectArgs.builder()
                    .object(filePath)
                    .contentType("image/jpg")
                    .bucket(minIOConfigProperties.getBucket()).stream(inputStream, inputStream.available(), -1)
                    .build();
            minioClient.putObject(putObjectArgs);
            StringBuilder urlPath = new StringBuilder(minIOConfigProperties.getReadPath());
            urlPath.append(separator + minIOConfigProperties.getBucket());
            urlPath.append(separator);
            urlPath.append(filePath);
            return urlPath.toString();
        } catch (Exception ex) {
            throw new RuntimeException("上传文件失败");
        }
    }

    /**
     * 上传html文件
     *
     * @param prefix      文件前缀
     * @param filename    文件名
     * @param inputStream 文件流
     * @return 文件全路径
     */
    @Override
    public String uploadHtmlFile(String prefix, String filename, InputStream inputStream) {
        String filePath = builderFilePath(prefix, filename);
        try {
            PutObjectArgs putObjectArgs = PutObjectArgs.builder()
                    .object(filePath) //文件名
                    .contentType("text/html")//文件类型
                    .bucket(minIOConfigProperties.getBucket())//桶名称与minio创建的桶一致
                    .stream(inputStream, inputStream.available(), -1)//文件流
                    .build();
            minioClient.putObject(putObjectArgs);
            StringBuilder urlPath = new StringBuilder(minIOConfigProperties.getReadPath());
            urlPath.append(separator + minIOConfigProperties.getBucket());
            urlPath.append(separator);
            urlPath.append(filePath);
            return urlPath.toString(); //文件全路径
        } catch (Exception ex) {
            ex.printStackTrace();
            throw new RuntimeException("上传文件失败");
        }
    }

    /**
     * 删除文件
     *
     * @param pathUrl 文件全路径
     */
    @Override
    public void delete(String pathUrl) {
        String key = pathUrl.replace(minIOConfigProperties.getEndpoint() + "/", "");
        int index = key.indexOf(separator);
        String bucket = key.substring(0, index);
        String filePath = key.substring(index + 1);
        // 删除Objects
        RemoveObjectArgs removeObjectArgs = RemoveObjectArgs.builder().bucket(bucket).object(filePath).build();
        try {
            minioClient.removeObject(removeObjectArgs);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }


    /**
     * 下载文件
     *
     * @param pathUrl 文件全路径
     * @return 文件流
     */
    @Override
    public byte[] downLoadFile(String pathUrl) {
        String key = pathUrl.replace(minIOConfigProperties.getEndpoint() + "/", "");
        int index = key.indexOf(separator);
        String bucket = key.substring(0, index);
        String filePath = key.substring(index + 1);
        InputStream inputStream = null;
        try {
            inputStream = minioClient.getObject(GetObjectArgs.builder().bucket(minIOConfigProperties.getBucket()).object(filePath).build());
        } catch (Exception e) {
            e.printStackTrace();
        }

        //字节数组输出流
        ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
        byte[] buff = new byte[100];
        int rc = 0;
        while (true) {
            try {
                if (!((rc = inputStream.read(buff, 0, 100)) > 0)) break;
            } catch (IOException e) {
                e.printStackTrace();
            }
            byteArrayOutputStream.write(buff, 0, rc);
        }
        return byteArrayOutputStream.toByteArray();
    }

}
4.7 编写controller进行测试
@RestController
@RequestMapping("/minio")
public class MinioController {

    @Autowired
    private FileStorageService fileStorageService;

    /**
     * 上传图片到minio
     *
     * @param file
     * @return
     */
    @PostMapping("/upload")
    public void uploadFile(MultipartFile file) throws IOException {
        try {
            // 获取文件名称
            String fileName = file.getOriginalFilename();
            /*解决多次上传同名文件覆盖问题*/
            // 在文件名称里面添加随机唯一的值
            String uuid = UUID.randomUUID().toString().replaceAll("-", "");
            fileName = uuid + fileName;
            // 获取文件输入流
            InputStream is = file.getInputStream();
            String imgUrl = fileStorageService.uploadImgFile("img", fileName, is);
            return "上传成功!imgUrl:"+imgUrl;
        } catch (IOException e) {
            e.printStackTrace();
            return "上传失败";
        }
    }

}
4.8 启动项目,测试

查看 Minio 可视化界面图片是否上传成功

可通过ip+图片路径直接访问。 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1384097.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

细说JavaScript语句详解

一、顺序结构 二、表达式语句 三、声明语句 四、条件语句 1、if语句 2、if…else语句 3、else if语句 4、switch语句 五、循环语句 1、while循环 2、do… while循环 3、for循环 4、for…in循环 六、跳出语句 1、label语句 2、break语句 3、continue语句

Go interface基础

接口类型是对其它类型行为的概括与抽象。通过使用接口&#xff0c;我们可以写出更加灵活和通用的函数&#xff0c;这些函数不用绑定在一个特定的类型实现上。 很多面向对象的语言都有接口这个概念&#xff0c;Go 语言的接口的独特之处在于它是隐式实现。换句话说&#xff0c;对…

在illustrator中按大小尺寸选择物体 <脚本 018>

在Illustrator中我们可以依据对象的属性 如:填充颜色、描边颜色或描边宽度来选择相同属性的对象,但是Illustrator中没有根据不同大小尺寸来选择对象的功能,下面介绍的就是根据大小尺寸选择对象的脚本。 1、下面是当前画板中的所有对象,我们想把一些在尺寸小一些的方形物体…

Zung氏焦虑症测试SAS

SAS被称为焦虑自评量表&#xff0c;是一种用来测量焦虑症状程度以及观察治疗过程中变化情况的心理量表。主要用于评估心理状态&#xff0c;辅助参考数据&#xff0c;也是焦虑评定的标准。焦虑自评量表系是由William W.K. Zung编制的&#xff0c;该量表已成为心理咨询师、心理医…

UDS 诊断通讯

UDS有哪些车型支持 UDS(统一诊断服务)协议被广泛应用于汽车行业中,支持多种车型。具体来说,UDS协议被用于汽车电子控制单元(ECU)之间的通讯,以实现故障诊断、标定、编程和监控等功能。 支持UDS协议的车型包括但不限于以下几种: 奥迪(Audi)车型:包括A3、A4、A5、A6…

C++学习笔记——SLT六大组件及头文件

目录 一、C中STL&#xff08;Standard Template Library&#xff09; 二、 Gun源代码开发精神 三、 实现版本 四、GNU C库的头文件分布 bits目录 ext目录 backward目录 iostream目录 stdexcept目录 string目录 上一篇文章&#xff1a; C标准模板库&#xff08;STL&am…

memory泄露分析方法(java篇)

#memory泄露主要分为java和native 2种&#xff0c;本文主要介绍java# 测试每天从monkey中筛选出内存超标的app&#xff0c;提单流转到我 首先&#xff0c;辨别内存泄露类型&#xff08;java&#xff0c;还是native&#xff09; 从采到的dumpsys_meminfo_pid看java heap&…

IPv6组播--SSM Mapping

概念 SSM(Source-Specific Multicast)称为指定源组播,要求路由器能了解成员主机加入组播组时所指定的组播源。 如果成员主机上运行MLDv2,可以在MLDv2报告报文中直接指定组播源地址。但是某些情况下,成员主机只能运行MLDv1,为了使其也能够使用SSM服务,组播路由器上需要提…

【用法总结】无障碍AccessibilityService

一、背景 本文仅用于做学习总结&#xff0c;转换成自己的理解&#xff0c;方便需要时快速查阅&#xff0c;深入研究可以去官网了解更多&#xff1a;官网链接点这里 之前对接AI语音功能时&#xff0c;发现有些按钮&#xff08;或文本&#xff09;在我没有主动注册唤醒词场景…

【手搓深度学习算法】用逻辑回归分类Iris数据集-线性数据篇

用逻辑回归分类Iris数据集-线性数据篇 前言 逻辑斯蒂回归是一种广泛使用的分类方法&#xff0c;它是基于条件概率密度函数的最大似然估计的。它的主要思想是将输入空间划分为多个子空间&#xff0c;每个子空间对应一个类别。在每个子空间内部&#xff0c;我们假设输入变量的取…

肯·汤普逊 :我心目中的神,好像真正无敌之上的大佬都对C++提出了批判!大佬们的思想像红太阳太耀眼,常人不能直视

肯尼斯蓝汤普逊&#xff08;英语&#xff1a;Kenneth Lane Thompson&#xff0c;1943年2月4日—&#xff09;&#xff0c;小名肯汤普逊&#xff08;英语&#xff1a;Ken Thompson&#xff09;&#xff0c;美国计算机科学学者和工程师。黑客文化圈子通常称他为“ken”[1]。在贝尔…

NLP论文阅读记录 - 2021 | WOS 使用深度强化学习及其他技术进行自动文本摘要

文章目录 前言0、论文摘要一、Introduction1.1目标问题1.2相关的尝试1.3本文贡献 二.相关工作2.1. Seq2seq 模型2.2.强化学习和序列生成2.3.自动文本摘要 三.本文方法四 实验效果4.1数据集4.2 对比模型4.3实施细节4.4评估指标4.5 实验结果4.6 细粒度分析 五 总结思考 前言 Auto…

Keil5如何生成反汇编文件

Keil5如何生成反汇编文件 在Keil5界面下点击选项&#xff0c;选择“User”&#xff0c;勾选“After Build/Rebuild”中“RUN #1”&#xff0c;复制fromelf --text -a -c --outputxxx.dis xxx.axf 在Linker栏中找到“Linker Control string”里最后-o后的.axf文件&#xff0c;将…

对资金类服务幂等设计与测试的思考

之前写过一篇《系统设计的幂等性》科普文章。 幂等性原本是数学上的概念&#xff0c;用在接口上就可以理解为&#xff1a;同一个接口&#xff0c;多次发出同一个请求&#xff0c;必须保证操作只执行一次。调用接口发生异常并且重复尝试时&#xff0c;总是会造成系统所无法承受的…

lenovo联想笔记本电脑拯救者Legion Y7000 2019 PG0(81T0)原装出厂Windows10系统

链接&#xff1a;https://pan.baidu.com/s/1fn0aStc4sfAfgyOKtMiCCA?pwdas1l 提取码&#xff1a;as1l 联想拯救者原厂Win10系统自带所有驱动、出厂主题壁纸、系统属性联机支持标志、系统属性专属LOGO标志、Office办公软件、联想电脑管家等预装程序 所需要工具&#xff1a;…

响应式Web开发项目教程(HTML5+CSS3+Bootstrap)第2版 例4-1 表单

代码 <!doctype html> <html> <head> <meta charset"utf-8"> <title>表单</title> </head><body> <!--<form action"URL地址" method"提交方式" name"表单名称" /*编码“多部…

数据在AI图像修复任务中的核心作用

在人工智能&#xff08;AI&#xff09;领域&#xff0c;数据的重要性不言而喻。尤其在图像修复任务中&#xff0c;数据的精度和质量直接影响着AI模型的性能。图像修复是指利用AI技术自动识别图像中的缺陷或遮挡物&#xff0c;并对其进行修复或还原的过程。这项技术广泛应用于各…

持续赋能波卡生态创新,OneBlock+ 社区 2023 年度回顾

OneBlock 开发者社区成立于 2018 年&#xff0c;历经五年的积累与沉淀&#xff0c;已经成长为行业内领先的 Substrate 开发者社区。我们以成熟的社区生态&#xff0c;通过 Substrate 技术与波卡生态的相关优质文章、项目方与开发者专访、线上线下技术热点对谈、多阶段开发者课程…

【设计模式】什么场景可以考虑使用简单工厂模式

1.概述 工厂模式是一种创建型模式&#xff0c;主要作用就是创建对象&#xff0c;将对象的创建过程和使用的过程进行解耦。我们平时说的工厂模式实际上是对三种不同类型的工厂模式的统称&#xff0c;简单工厂、工厂方法、抽象工厂&#xff0c;而在23种设计模式中&#xff0c;只…

AI绘画风格化实战

在社交软件和短视频平台上&#xff0c;我们时常能看到各种特色鲜明的视觉效果&#xff0c;比如卡通化的图片和中国风的视频剪辑。这些有趣的风格化效果其实都是图像风格化技术的应用成果。 风格化效果举例 MidLibrary 这个网站提供了不同的图像风格&#xff0c;每一种都带有鲜…