MinIO - 从 环境搭建 -> SpringBoot实战 -> 演示,掌握 Bucket 和 Object 操作

目录

开始

Docker 部署

MinIO 中的基本概念

SpringBoot 集成 MinIO

依赖

配置

MinIO 时间差问题报错 The difference between the request time and the server`s time is too large

MinIO 中对 Bucket(文件夹) 的操作

是否存在 / 创建

查询所有文件夹

删除文件夹

MinIO 中对 Object(文件) 的操作

两种文件上传的方式

查看文件状态(是否存在)

生成带签名的URL路径

怎么使用不带签名的 url 直接访问

从 MinIO 上获取图片,然后下载到本地磁盘'

获取文件夹下的所有文件


开始


Docker 部署

a)拉取镜像

docker pull minio/minio

 b)创建挂载点

mkdir -p ~/env/minio/conf
mkdir -p ~/env/minio/data

 c)运行

这里设置了 MinIO 的用户名和密码,注意密码不能少于 8 位

docker run -d \
--name minio \
-p 9000:9000 \
-p 9001:9001 \
--privileged=true \
-e "MINIO_ROOT_USER=root" \
-e "MINIO_ROOT_PASSWORD=rootroot" \
-v ~/env/minio/data:/data \
-v ~/env/minio/conf:/root/.minio \
minio/minio server \
--console-address ":9000" \
--address ":9001" /data

 d)访问:http://env-base:9000

MinIO 中的基本概念

Bucket:相当于存放文件的文件夹,用来存储 Object 的逻辑空间.

Object:相当于文件,是存储到 MinIO 中的基本对象.

Ps:Minio 存在线程安全问题么?

Minio 是线程安全的,即使在 SpringBoot 中 Bean 是使用单例模式的(作者在 github 上的回复).

SpringBoot 集成 MinIO

依赖

Note:官网地址 Software Development Kits (SDK) — MinIO Object Storage for Linux

Maven 如下 

<dependency><groupId>io.minio</groupId><artifactId>minio</artifactId><version>8.5.11</version>
</dependency>

Gradle 如下

dependencies {implementation("io.minio:minio:8.5.11")
}

配置

由于 MinIO 没有 SpringBootStarter 相关的依赖,因此配置类需要我们自己来写~

import io.minio.MinioClient
import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration@Configuration
class MinioConfig {@Beanfun minioClient(): MinioClient = MinioClient.builder().endpoint("http://100.105.180.32:9001") //格式必须是 http://ip:port  注意: 这里使用的 9001 端口,而不是 9000.credentials("root", "rootroot") //用户名 和 密码.build()}

MinIO 时间差问题报错 The difference between the request time and the server`s time is too large

如果出现了上述报错,说明你的主机和服务器上的时间不一致.

解决如下:

a)下载 ntpdate,用来同步主机和服务器的时间.

yum install ntpdate -y

b)同步时间,如下命令

ntpdate pool.ntp.org

MinIO 中对 Bucket(文件夹) 的操作

是否存在 / 创建

案例:如果不存在 dir1 文件夹,就创建.

@SpringBootTest
class MinioApplicationTests {@Resourceprivate lateinit var minioClient: MinioClient/*** 如果文件夹 dir1 不存在就创建*/@Testfun test1() {val exists = minioClient.bucketExists(BucketExistsArgs.builder().bucket("dir1").build())if (!exists) {minioClient.makeBucket(MakeBucketArgs.builder().bucket("dir1").build())} else {println("文件夹已经存在!")}}}

 第一次运行,可以看到会创建出这个文件夹:

第二次运行就会进行提示:

查询所有文件夹

如下代码:

    @Testfun test2() {val bucketList = minioClient.listBuckets()bucketList.forEach { bucket ->println("${bucket.name()} -- ${bucket.creationDate()}")}}

现在 MinIO 上有两个文件夹,如下: 

运行结果如下:

删除文件夹

案例:删除文件夹 dir2

    @Testfun test3() {minioClient.removeBucket(RemoveBucketArgs.builder().bucket("dir2").build())}

MinIO 中对 Object(文件) 的操作

两种文件上传的方式

案例:将本地 "D:/tmp/滑稽.gif" 图片上传到 MinIO 的 "dir1" 文件夹下,并重命名为 "test.gif" 

a)stream 方式

    @Testfun test1() {val file = File("D:/tmp/滑稽.gif")minioClient.putObject(PutObjectArgs.builder().bucket("dir1").`object`("test.gif")//stream://第二个参数(long objectSize): 要上传的文件大小//第三个参数(long partSize): 指定缓冲区的大小//这两个如果不知道,都可以使用 -1.stream(FileInputStream(file), file.length(), -1).build())}

b) upload 方式(更简单一些)

    @Testfun test2() {minioClient.uploadObject(UploadObjectArgs.builder().bucket("dir1").`object`("test.gif").filename("D:/tmp/滑稽.gif").build())}

 c)运行结果在 MinIO 上可以观察到:

相比较上面的上传文件的方式,以下这种上传文件的方式就更加简单

查看文件状态(是否存在)

案例:查询 "dir1" 文件夹下的 "test.gif" 文件的状态

    @Testfun test3() {val result = minioClient.statObject(StatObjectArgs.builder().bucket("dir1").`object`("test.gif").build())println(result)}

a)如果文件存在,运行结果如下:

b)如果文件不存在,抛出异常如下:

c)对于文件不存在的情况,也可以做出如下处理

    @Testfun test3() {try {val result = minioClient.statObject(StatObjectArgs.builder().bucket("dir1").`object`("testa1.gif").build())println(result)} catch (e: ErrorResponseException) {println("文件不存在!")println(e.message)}}

 运行结果如下:

生成带签名的URL路径

案例:给 MinIO 上的 "dir1" 文件夹下的 "test.gif" 文件生成一个带签名的 url 路径(get 请求).

    @Testfun test4() {val url = minioClient.getPresignedObjectUrl(GetPresignedObjectUrlArgs.builder().bucket("dir1").`object`("test.gif").method(Method.GET) //指定生成的 url 请求方式// .expiry(3, TimeUnit.SECONDS) 设置签名的过期时间.build())println(url)}

运行结果如下:

通过这个 url 就可以访问到图片

怎么使用不带签名的 url 直接访问

a)后台修改

下图位置,可以设置成 public 的,这样就可以通过不带签名的 url 直接访问到图片.

这样所有用户都能访问这个图片.

值得注意的是,如果设置成 public,会比较危险,因为这样意味着所有用户都能对这个桶下的文件进行 增删改查...

不过也可以给这个文件夹赋予只读权限(只有登录了 MinIO 的用户才能进行其他操作,比如你的程序最开始配置了 MinioClient,才可以进行其他操作):

再返回来,就可以看到该文件夹自动变成了自定义的权限:

打开就可以看到给你自动生成的 json 文件来实现针对 url 的只读权限控制:

b)创建桶的时候指定访问策略(只允许读操作)

Ps:代码中的 jsonConfig 就是从第一种方式中生成的 json 文件复制过来就可以,但是注意要修改以下文件名!

    @Testfun test5() {//新建文件夹 dir2minioClient.makeBucket(MakeBucketArgs.builder().bucket("dir2").build())//设置文件夹的访问权限为 只读val jsonConfig = """
{"Version": "2012-10-17","Statement": [{"Effect": "Allow","Principal": {"AWS": ["*"]},"Action": ["s3:GetBucketLocation"],"Resource": ["arn:aws:s3:::dir2"]},{"Effect": "Allow","Principal": {"AWS": ["*"]},"Action": ["s3:ListBucket"],"Resource": ["arn:aws:s3:::dir2"],"Condition": {"StringEquals": {"s3:prefix": ["*"]}}},{"Effect": "Allow","Principal": {"AWS": ["*"]},"Action": ["s3:GetObject"],"Resource": ["arn:aws:s3:::dir2/**"]}]
}""".trimIndent()minioClient.setBucketPolicy(SetBucketPolicyArgs.builder().bucket("dir2").config(jsonConfig).build())//上传图片minioClient.uploadObject(UploadObjectArgs.builder().bucket("dir2").`object`("test.gif").filename("D:/tmp/滑稽.gif").build())val url = minioClient.getPresignedObjectUrl(GetPresignedObjectUrlArgs.builder().bucket("dir2").`object`("test.gif").method(Method.GET).build()).split("?")[0] //这样就可以不需要 签名 部分了println(url)}

运行结果如下: 

 

之后就可以直接不带 签名档 url 通过 url 来访问啦~

从 MinIO 上获取图片,然后下载到本地磁盘'

案例:获取 文件夹"dir1" 中的 "test.gif"文件 ,保存到本地磁盘的 "D:/tmp/" 路径下,并重命名为 "123.gif"

    @Testfun test6() {val resp = minioClient.getObject(GetObjectArgs.builder().bucket("dir1").`object`("test.gif").build())val file = FileOutputStream("D:/tmp/123.gif")val result = resp.transferTo(file)println(result)}

 运行结果如下:

获取文件夹下的所有文件

案例:获取 dir1 文件夹下的所有文件名

    @Testfun test7() {val objects = minioClient.listObjects(ListObjectsArgs.builder().bucket("dir1").build())objects.forEach { result ->val item = result.get()println(item.objectName())}}

 运行结果如下:

删除文件

案例:删除文件夹 "dir1" 中的 test2.jpg 文件.

    @Testfun test8() {minioClient.removeObject(RemoveObjectArgs.builder().bucket("dir1").`object`("test2.jpg").build())}

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

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

相关文章

Apache Seata 源码分析Seata-XID传递 Dubbo篇

本文来自 Apache Seata官方文档&#xff0c;欢迎访问官网&#xff0c;查看更多深度文章。 本文来自 Apache Seata官方文档&#xff0c;欢迎访问官网&#xff0c;查看更多深度文章。 源码分析 Seata-XID 传递 Dubbo 篇 本文作者&#xff1a;FUNKYE(陈健斌),杭州某互联网公司主…

TQ15EG开发板教程:MPSOC创建fmcomms8工程

链接&#xff1a;https://pan.baidu.com/s/1jbuYs9alP2SaqnV5fpNgyg 提取码&#xff1a;r00c 本例程需要实现在hdl加no-OS系统中&#xff0c;通过修改fmcomms8/zcu102项目&#xff0c;实现在MPSOC两个fmc口上运行fmcomms8项目。 目录 1 下载文件与切换版本 2 编译fmcomms8项…

超越YOLO! RT-DETR 实时目标检测技术介绍

《博主简介》 小伙伴们好&#xff0c;我是阿旭。专注于人工智能、AIGC、python、计算机视觉相关分享研究。 ✌更多学习资源&#xff0c;可关注公-仲-hao:【阿旭算法与机器学习】&#xff0c;共同学习交流~ &#x1f44d;感谢小伙伴们点赞、关注&#xff01; 《------往期经典推…

免杀笔记 ----> DLL注入

这段时间我们暂时没什么事情干的话我们就继续更新我们的免杀笔记力&#xff01;&#xff01;&#xff01; &#xff1a;今天我们讲DLL注入 目录 1.DLL注入 2.直接加载DLL&#xff1f; 3.远程线程注入 获取Handle 远程申请内存空间 将我们的CS的DLL加载入内存 创建远程线…

02:C语言数据类型

C语言数据类型 1、整型变量2、浮点型变量3、字符型变量4、有符号数和无符号数 1、整型变量 #include <stdio.h>int main(void) { /* int a; //定义一个整型变量aint b; //定义一个整型变量bint c; //定义一个整型变量c */ /* int a,b,c; //也可以这样定义a 25;b 6; *…

【Linux】进程信号_4

文章目录 八、进程信号3. 信号的处理4. 可重入函数5. volatile 未完待续 八、进程信号 3. 信号的处理 当某个信号的处理函数被调用时&#xff0c;操作系统会自动将当前信号假如进程的信号屏蔽字当中。如果处理完该信号&#xff0c;该信号同样也会自动从信号屏蔽字中 移除。该…

Apache Seata core 模块源码分析

本文来自 Apache Seata官方文档&#xff0c;欢迎访问官网&#xff0c;查看更多深度文章。 本文来自 Apache Seata官方文档&#xff0c;欢迎访问官网&#xff0c;查看更多深度文章。 一 . 导读 core 模块定义了事务的类型、状态&#xff0c;通用的行为&#xff0c;client 和 s…

毕业季有感

本文介绍一些刚毕业、即将入职前的随想与心得。 毕业和上班无缝衔接。要离开北京了&#xff0c;来到天津。 我一向很喜欢探索新环境&#xff0c;每一次要到新的学校、新的城市、新的单位都会很激动&#xff1b;这一次也是一样&#xff0c;在一开始几乎只有对新环境的憧憬。但是…

7.6第三天作业

一、在数据库中创建一个表student&#xff0c;用于存储学生信息 CREATE TABLE student( id INT PRIMARY KEY, name VARCHAR(20) NOT NULL, grade FLOAT ); &#xff08;1.&#xff09;先创建一个数据库 &#xff08;2.&#xff09;创建student表 查看是否创建成功 1、向studen…

http读书笔记

持久化 HTTP/1.1 和一部分的 HTTP/1.0 想出了 持久连接&#xff08;HTTP Persistent Connections&#xff0c; 也称为 HTTP keep-alive 或 HTTP connection reuse&#xff09; 的方法。 持久连接的特点是&#xff0c; 只要任意一端 没有明确提出断开连接&#xff0c; 则保持 T…

MySQL第三天作业

一、在数据库中创建一个表student&#xff0c;用于存储学生信息 CREATE TABLE student( id INT PRIMARY KEY, name VARCHAR(20) NOT NULL, grade FLOAT ); 1、向student表中添加一条新记录 记录中id字段的值为1&#xff0c;name字段的值为"monkey"…

【Linux】查找命令——which,type,find,whereis,locate

命令与文件的查找 文件的查找可就厉害了&#xff0c;因为我们常常需要知道哪个文件放在哪里&#xff0c;才能够对该文件进行一些修改或维护等操作。 有时候某些软件配置文件的文件名是不变的&#xff0c;但是各Linux发行版放置的目录则不同。 此时就要利用一些查找命令将该配…

25.【C语言】循环结构之for 上

1.基本使用 类比while 在while循环中&#xff0c;有三个不可或缺的部分&#xff1a;初始化&#xff0c;判断部分&#xff0c;调整部分 int i 0;//初始化 while (i < 10)//判断部分 {……i;//调整部分 }三个部分太分散&#xff0c;用for循环可集为一体&#xff0c;简洁 …

使用shell脚本实现DM8开机自动启动

编写shell脚本 #!/bin/bashsu -dmdba >>EOF cd /home/dmdba/dmdbms/bin ./DmServiceDMTEST start echo "dm start ... " EOF注意&#xff1a;DmServiceDMTEST每个服务器设置的不一样&#xff0c;根据实际进行更换 授权脚本可执行权限 chmod -x /dmdata/dmse…

搭建互联网医院实战:从源码到在线问诊APP的全流程开发

今天&#xff0c;笔者将讲述在线问诊APP的全流程开发&#xff0c;帮助开发者理解和掌握搭建互联网医院的核心技术和步骤。 一、需求分析与设计 需求分析包括明确目标用户、功能需求、性能需求等。设计阶段则包括系统架构设计、数据库设计和前后端界面设计等。 1.目标用户&…

最小权顶点覆盖问题-优先队列分支限界法-C++

问题描述: 给定一个赋权无向图 G(V,E)&#xff0c;每个顶点 v∈V 都有一个权值 w(v)。如果 U⊆V&#xff0c;U⊆V&#xff0c;且对任意(u,v)∈E 有 u∈U 或 v∈U&#xff0c;就称 U 为图 G 的一个顶点覆盖。G 的最小权顶点覆盖是指 G 中所含顶点权之和最小的顶点覆盖。对于给定…

提取重复数据

直接上控制台代码&#xff1a; Module Module1Sub Main()Console.WriteLine("请输入数据&#xff0c;以""&#xff0c;""相隔&#xff1a;")Dim str As String Console.ReadLineDim result From x In str.Split(",")Group By x Int…

NTP协议格式解析

1. NTP时间戳格式 SNTP使用在RFC 1305 及其以前的版本所描述标准NTP时间戳的格式。与因特网标准标准一致&#xff0c; NTP 数据被指定为整数或定点小数&#xff0c;位以big-endian风格从左边0位或者高位计数。除非不这样指定&#xff0c;全部数量都将设成unsigned的类型&#…

Android Graphics 显示系统 - 监测、计算FPS的工具及设计分析

“ 在Android图像显示相关的开发、调试、测试过程中&#xff0c;如何能有效地评估画面的流畅度及监测、计算图层渲染显示的实时FPS呢&#xff1f;本篇文章将会提供一种实用、灵巧的思路。” 01 设计初衷 面对开发测试中遇到的卡顿掉帧问题&#xff0c;如何在复现卡顿的过程中持…

代码随想录算法训练营第四十五天| 300.最长递增子序列、 674. 最长连续递增序列、 718. 最长重复子数组

300.最长递增子序列 题目链接&#xff1a;300.最长递增子序列 文档讲解&#xff1a;代码随想录 状态&#xff1a;不会&#xff0c;递推状态的时候只想着如何从dp[i-1]推导dp[i]&#xff0c;没想过可能需要枚举dp[0-i] 思路&#xff1a; 找出所有比自己小的数字的dp[j],在这些dp…