Minio学习
一、Minio概述
根据官网的描述,minio
是一种用于人工智能基础建设的对象存储。即一款可以存储海量数据的对象存储软件(或服务器)。
二、Minio启动
因为我自己是在ubuntu环境下配置的minio
服务器,所以我只记录在linux上的启动方法
步骤一:wget https://dl.min.io/server/minio/release/linux-amd64/minio
步骤二:chmod +x minio | chmod 744 minio
步骤三:MINIO_ROOT_USER=admin MINIO_ROOT_PASSWORD=password ./minio server /mnt/data --console-address ":9001"
这是官网上给出的方法。第一步就是将minio
下载到我们的linux系统上。第二步修改minio
这个文件的权限,让其拥有执行权限。第三步启动minio服务。
关于启动命令分解
启动命令:MINIO_ROOT_USER=admin MINIO_ROOT_PASSWORD=password ./minio server /mnt/data --console-address ":9001"
1:MINIO_ROOT_USER=admin 指定访问minio服务的用户名
2:MINIO_ROOT_PASSWORD=password 指定访问minio服务的密码
3:./minio server /mnt/data --console-address ":9001" 启动minio服务并将服务产生的数据输出到/mnt/data下
4:--console-address ":9001" 指定minio服务器控制台的访问地址
5:--address 指定minio服务器监听的S3 API访问地址
关于--console-address
和--address
的区别可以参考这篇文章:minio中的安装启动地址问题
在启动命令的最后面加上一个&
表示在后台运行minio服务,即按下ctrl + c
后服务并不会结束(不加&
按下 ctrl + c
服务立即结束)
示例:MINIO_ROOT_USER=admin MINIO_ROOT_PASSWORD=password ./minio server /mnt/data --console-address ":9001" &
效果图如下:
三、Minio关闭
minio
服务作为一个进程运行在linux服务器上,因此要关闭minio
服务器只需要杀掉minio
这个进程就行了。
-
查看某一个具体服务的进程相关信息(
pid
)ps -ef | grep minio
-
如何杀掉一个进程
kill pid 示例:kill 1234
四、在SpringBoot中对minio服务器进行编程
4.1引入minio客户端的依赖
复制官网为我们提供的依赖坐标,引入jar包依赖。官网地址:Software Development Kits (SDK) — MinIO Object Storage for Linux
<dependency>
<groupId>io.minio</groupId>
<artifactId>minio</artifactId>
<version>8.5.11</version>
</dependency>
4.2将minio的客户端对象配置到IOC容器中
因为minio
的SDK并没有和springboot
结合在一起,也就是没有springboot-starter-xxx
的这种依赖,所以我们引入了依赖后,minio
客户端对象并不会自动加入到IOC容器中,所以我们需要手动配置一下。
配置方法:自己创建一个配置类,然后在配置类中将minio
客户端对象加入到IOC
容器
示例:
/*定义配置类,将minio客户端对象加入到IOC容器中*/
@Configuration
public class MinioConfig {
@Bean
public MinioClient getMinioClient(){
/*构建minio客户端对象需要两个参数
* 1、访问minio服务器的地址url
* 2、minio服务器的用户名和密码
* */
return MinioClient
.builder()
//设置minio服务器的访问路径
//这里的路径配置到yml文件中会更合理
.endpoint(" http://172.23.152.117:9000")
//设置访问minio服务器需要的用户名和密码
.credentials("admin","admin123")
.build();
}
}
进行如上配置后我们就可以在我们需要使用到minio
客户端对象的地方直接将其注入进去就行了。
五、上传文件
在minio
中有两个比较重要的概念:桶和对象,即(bucket
和object
)。桶是存放对象的顶级容器,通俗来是桶就是我们平时熟悉的文件夹,对象就是文件,文件夹里面存放文件,那桶里面存放对象也就更容易理解了。
理解了桶和对象的概念以后,那就清楚我们需要做什么了,我们要对minio
服务器编程,无非就是我们需要将我们的文件上传到minio
服务器上,然后能从服务器上获取到文件,那我们需要学习的无非就是如何上传文件和下载文件了。
5.1桶操作
试想一下我们平时要保存一个文件首先要做什么呢?那当然是先创建一个文件夹吧,那我们要将文件上传到minio
服务器上并保存第一步就是要创建一个桶(文件夹)。
5.1.1创建桶
使用public void makeBucket(MakeBucketArgs args)
方法可以创建一个桶。示例代码如下
minioClient.makeBucket(MakeBucketArgs
.builder()
//设置桶的名字
.bucket("mybucket")
.build());
ps:你无法创建一个已经存在的桶,如果你试图那样做的话minio
服务器将会抛出如下异常。
5.1.2遍历服务器中的所有桶
使用public List<Bucket> listBuckets()
方法可以获取到服务器中所有桶对象的集合。遍历集合拿到每一个桶对象,一个桶对象中包含了两个信息:1、桶的名字;2、桶的创建时间。示例代码如下
List<Bucket> bucketList = minioClient.listBuckets();
bucketList.forEach(bucket -> {
System.out.println("桶"+bucket.name()+"创建时间为"+bucket.creationDate());
});
5.1.3删除桶
如果你想要删除一个桶,那么你可以使用public void removeBucket(RemoveBucketArgs args)
方法。示例代码如下。
minioClient.removeBucket(RemoveBucketArgs
.builder()
.bucket("mybucket")
.build());
ps:如果尝试删除一个不存在的桶,minio
服务器也会抛出异常。
5.2对象操作
学会了如何操作桶之后,我们就应该学习如何操作对象了,也就是如何上传文件和下载文件了。
5.2.1上传对象(文件)
使用public ObjectWriteResponse putObject(PutObjectArgs args)
方法可以上传一个object
(文件)。示例代码如下
//这里填入要上传文件的本地地址
File file = new File("filePath");
ObjectWriteResponse writeResponse = minioClient.putObject(PutObjectArgs
.builder()
//这里填入要存到minio服务器上的哪个桶中
.bucket("bucketName")
//这里填入文件的名字,这个名字是自己设置的,最好要保证这个名字是唯一的,不然会覆盖掉已经存在的且和他同名的对象
.object("objectName")
//这里的第三个参数建议传入-1
.stream(Files.newInputStream(file.toPath()), file.length(), -1)
.build());
关于stream
中第三个参数说明:
这是源码中对objectSize
和partSize
的解释,大概意思就是如果文件的大小是未知的,那么objectSize
传递-1
,partSize
传递有效值;如果文件大小是已知的那么partSize
传递-1
否则partSize
需要传递一个有效值;如果partSize
比objectSize
大得多的话objectSize
的值就会被当作partSize
的值。partSize
的取值范围是5MiB~5GiB
,objectSize
的最大取值为5TiB
。
除了上述方法外,我们还可以通过public ObjectWriteResponse uploadObject(UploadObjectArgs args)
方法上传object
(文件)。示例代码如下
minioClient.uploadObject(UploadObjectArgs
.builder()
.bucket("bucketName")
.object("objectName")
.filename("filePath")
.build());
以上两种方式都可以上传一个对象(文件),但是我认为第一种对于我们后台开发人员来说更为适用,因为绝大多情况下我们需要上传的文件都来源于前端,而前端传递文件到后端的方法无非就是通过流来传输的,所以直接通过第一种方法更为方便。
ps:如果两次上传文件的名字是相同的话,那后面上传的文件会覆盖掉原来上传的文件,所以在上传文件的时候我们一定要保证文件名的唯一性。
5.2.2判断对象(文件)是否存在
使用public StatObjectResponse statObject(StatObjectArgs args)
方法可以判断指定对象名的对象是否存在。示例代码如下
StatObjectResponse response = minioClient.statObject(StatObjectArgs
.builder()
.bucket("bucketName")
.object("objectName")
.build());
System.out.println(response);
其中返回的StatObjectResponse
对象结构如下:
其中包含了对象的一些基础信息。
如果指定对象名的对象不存在,那么minio
服务器会抛出如下异常
5.2.3获取对象(文件)的url
我们在实际的项目开发中访问某个文件的方法就是直接在浏览器中输入这个文件的url
然后回车,因此我们需要获取到我们的文件的url
供其他用户访问。
使用public String getPresignedObjectUrl(GetPresignedObjectUrlArgs args)
方法可以获取到指定名字的对象的url。示例代码如下
String url = minioClient.getPresignedObjectUrl(GetPresignedObjectUrlArgs
.builder()
.bucket("mybucket")
.object("test.jpg")
.method(Method.GET)
.build());
System.out.println(url);
返回结果如下
http://172.23.152.117:9000/mybucket/test.jpg?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=admin%2F20240718%2Fus-east-1%2Fs3%2Faws4_request&X-Amz-Date=20240718T083406Z&X-Amz-Expires=604800&X-Amz-SignedHeaders=host&X-Amz-Signature=97d097fd80b5316279aba47bb06be45d58a0189b01240d1da36a708700f57641
很显然,这个url除了我们比较常见的部分外后面还跟了一串字符串。?
后面的内容其实是minio服务器下发的数字签名,也就是说只有拥有数字签名的用户才能访问到我们的对象。但是我们一般的场景都希望别人不加数字签名也能访问到我们的对象,那这个时候我们就要自定义minio
服务器中桶的权限了。
5.2.3.1桶的权限控制策略
在minio
服务器中桶有三种权限:Private
、Public
、Custom
Private
私有权限:顾名思义这个权限下的桶只能自己访问,其他人访问就需要拥有数字签名,否则无法访问
Public
公共权限:这种权限下的桶可以被其他人访问、修改、甚至删除
其实上面的这两种权限都不符合我们实际开发的需要,在实际的开发中我们一般希望我们的文件可以被别人访问,但是不希望别人能够修改、删除我们的文件。所以我们需要使用第三种权限。
Custom
自定义权限:在这种权限下我们可以自由定义桶的权限。在学习如何自定义桶的权限之前,我们要先学习一下S3标准策略语法
5.2.3.1.1S3标准策略语法
示例
{
"Version": "2012-10-17",//指定策略语言的版本。当前版本通常是 2012-10-17。这里必须填2012-10-17否则会报错
"Statement": [
{
"Effect": "Allow",//定义语句的效果。可以是 Allow 或 Deny。Allow:允许指定的动作;Deny:拒绝指定的动作。
//指定可以访问资源的主体。可以是 *(任何主体即所有人),或者指定用户、角色、账户等。
"Principal": {
"AWS": [
"*"
]
},
//定义允许或拒绝的操作。操作是资源上可以执行的具体行为。
"Action": [
"s3:GetBucketLocation",//获取桶的位置
"s3:ListBucket"//列出桶中的对象
//s3:GetObject:获取桶中的对象。
],
//定义策略适用的资源。通常是资源的 ARN(Amazon Resource Name)。可以包括桶或对象的 ARN。
"Resource": [
"arn:aws:s3:::mybucket"//指定桶 mybucket
//arn:aws:s3:::mybucket/*:指定桶 mybucket 中的所有对象。
]
}
]
}
所以我们要自定义用户对我们的对象(文件)只具有可读权限,就应该像下面这样设置S3策略语法
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"AWS": [
"*"
]
},
"Action": [
"s3:GetObject"
],
"Resource": [
"arn:aws:s3:::mybucket/*"
]
}
]
}
自定义权限控制策略有两种办法,一种是通过代码设置,另外一种是直接在minio
控制台直接设置。接下来我会分别介绍这两种方式。
5.2.3.2通过代码设置权限控制策略
使用public void setBucketPolicy(SetBucketPolicyArgs args)
方法可以设置minio
服务器的权限控制策略。示例代码如下。
minioClient.setBucketPolicy(SetBucketPolicyArgs.builder()
//桶名字
.bucket("mybucket")
//S3标准策略字符串
.config("{\n" +
" \"Version\": \"2012-10-17\",\n" +
" \"Statement\": [\n" +
" {\n" +
" \"Effect\": \"Allow\",\n" +
" \"Principal\": {\n" +
" \"AWS\": [\n" +
" \"*\"\n" +
" ]\n" +
" },\n" +
" \"Action\": [\n" +
" \"s3:GetObject\"\n" +
" ],\n" +
" \"Resource\": [\n" +
" \"arn:aws:s3:::mybucket/*\"\n" +
" ]\n" +
" }\n" +
" ]\n" +
"}").build());
5.2.3.3控制台设置权限控制策略
按照如下步骤可在minio
控制台设置权限控制策略。