官方文档:https://min.io/docs/minio/kubernetes/upstream/index.html?ref=docs-redirect
SDK:https://github.com/minio/minio-java
Minio 提供了多种语言的SDK,比如java、go、python等。JAVA开发平台可以选择JS和java SDK,也就是前端和后端都可以直接集成minio。
每个OSS的用户都会用到上传服务。Web端常见的上传方法是用户在浏览器或App端上传文件到应用服务器,应用服务器再把文件上传到OSS。具体流程如下图所示。
和数据直传到OSS相比,以上方法有三个缺点:
上传慢:用户数据需先上传到应用服务器,之后再上传到OSS。网络传输时间比直传到OSS多一倍。如果用户数据不通过应用服务器中转,而是直传到OSS,速度将大大提升。而且OSS采用BGP带宽,能保证各地各运营商之间的传输速度。
扩展性差:如果后续用户多了,应用服务器会成为瓶颈。
费用高:需要准备多台应用服务器。由于OSS上传流量是免费的,如果数据直传到OSS,不通过应用服务器,那么将能省下几台应用服务器。
目前通过Web前端技术上传文件到OSS,有三种技术方案:
利用OSS js SDK将文件上传到OSS,也就是前端直连OSS,但是容易暴露认证信息,安全性不太高。
使用表单上传方式,将文件上传到OSS。利用OSS提供的接口临时接口,使用表单上传方式将文件上传到OSS。然后请求后端,告知上传完成,进行后续处理。
先上传到应用服务器,再请求OSS上传,这种安全性较高,可以对数据和认证进行管控,但是性能最差。
因为一般的非互联网项目,对性能要求不高,所以采用JAVA SDK集成MInio,然后提供接口给Web端调用就行了。
首先搭建一个Maven基础工程,引入相关依赖,这里引入的是最新的8.3.1版本。还引入了okhttp的最新包,不然某些API会提示版本太低。
<dependency>
<groupId>io.miniogroupId>
<artifactId>minioartifactId>
<version>8.3.1version>
dependency>
<dependency>
<groupId>com.squareup.okhttp3groupId>
<artifactId>okhttpartifactId>
<version>4.9.2version>
dependency>
可以看到现在minio都是采用Builder构建者模式来构造对象,和之前有很大的区别,所以需要注意。
//url为地址,accessKey和secretKey为用户名和密码
MinioClient minioClient = MinioClient.builder().endpoint(url)
.credentials(accessKey, secretKey).build();
检查存储桶是否存在。
public boolean bucketExists(BucketExistsArgs args)
示例代码:
/**
* 判断桶是否存在
*/
public static boolean bucketExists(String url, String accessKey, String secretKey, String bucketName)
throws ServerException, InsufficientDataException, ErrorResponseException, IOException, NoSuchAlgorithmException, InvalidKeyException, InvalidResponseException, XmlParserException, InternalException {
MinioClient minioClient = MinioClient.builder().endpoint(url)
.credentials(accessKey, secretKey).build();
return minioClient.bucketExists(BucketExistsArgs.builder().bucket(bucketName).build());
}
创建一个启用给定区域和对象锁定功能的存储桶。
public void makeBucket(MakeBucketArgs args)
示例代码:
/**
* 添加存储桶
*/
public static void makeBucket(String url, String accessKey, String secretKey, String bucketName, String region, boolean objectLock)
throws ServerException, InsufficientDataException, ErrorResponseException, IOException, NoSuchAlgorithmException, InvalidKeyException, InvalidResponseException, XmlParserException, InternalException {
MinioClient minioClient = MinioClient.builder().endpoint(url)
.credentials(accessKey, secretKey).build();
minioClient.makeBucket(MakeBucketArgs.builder().bucket(bucketName).region(region).objectLock(objectLock).build());
}
创建后,就可以在控制台看到这些存储桶了,最后那个被锁定的存储桶,上传文件及删除后,发现还是会显示存在这些对象,实际磁盘上的文件并没有删除
列出所有桶的桶信息。
public List<Bucket> listBuckets()
示例代码:
/**
* 查询存储桶信息列表
*/
public static List<Bucket> listBuckets(String url, String accessKey, String secretKey) throws ServerException, InsufficientDataException, ErrorResponseException, IOException, NoSuchAlgorithmException, InvalidKeyException, InvalidResponseException, XmlParserException, InternalException {
MinioClient minioClient = MinioClient.builder().endpoint(url)
.credentials(accessKey, secretKey).build();
return minioClient.listBuckets();
}
public static void main(String[] args) throws ServerException, InsufficientDataException, ErrorResponseException, IOException, NoSuchAlgorithmException, InvalidKeyException, InvalidResponseException, XmlParserException, InternalException {
List<Bucket> buckets = listBuckets("url", "accessKey", "secretKey");
for (Bucket bucket : buckets) {
System.out.println(bucket.creationDate() + ", " + bucket.name());
}
}
删除一个空桶。
public void removeBucket(RemoveBucketArgs args)
示例代码:
/**
* 删除存储桶
*/
public static void removeBucket(String url, String accessKey, String secretKey, String bucketName)
throws ServerException, InsufficientDataException, ErrorResponseException, IOException, NoSuchAlgorithmException, InvalidKeyException, InvalidResponseException, XmlParserException, InternalException {
MinioClient minioClient = MinioClient.builder().endpoint(url)
.credentials(accessKey, secretKey).build();
minioClient.removeBucket(RemoveBucketArgs.builder().bucket(bucketName).build());
}
注意:要确保存储桶存在,否则会报错,删除时最好调用bucketExists()方法判断是否存在
设置桶的加密配置,以允许在该桶中上传对象时,采用对应加密配置对数据进行加密。当前支持配置的服务端加密方式为KMS托管密钥的服务端加密(SSE-KMS),及AES256加密。
设置桶的加密配置:
public void setBucketEncryption(SetBucketEncryptionArgs args)
获取桶的加密配置:
public SseConfiguration getBucketEncryption(GetBucketEncryptionArgs args)
生命周期管理可适用于以下典型场景:
周期性上传的日志文件,可能只需要保留一个星期或一个月。到期后要删除它们。
某些文档在一段时间内经常访问,但是超过一定时间后便可能不再访问了。这些文档需要在一定时间后转化为低频访问存储,归档存储或者删除。
存储桶生命周期配置:
public void setBucketLifecycle(SetBucketLifecycleArgs args)
获取桶的生命周期配置:
public LifecycleConfiguration getBucketLifecycle(GetBucketLifecycleArgs args)
示例代码:
// 5. 生命周期
List<LifecycleRule> rules = new LinkedList<>();
// 配置生命周期规则
rules.add(
new LifecycleRule(
Status.ENABLED, // 开启状态
null,
new Expiration((ZonedDateTime) null, 365, null), // 保存365天
new RuleFilter("logs/"), // 目录配置
"rule2",
null,
null,
null));
LifecycleConfiguration lifecycleConfiguration = new LifecycleConfiguration(rules);
// 添加生命周期配置
minioClient.setBucketLifecycle(
SetBucketLifecycleArgs.builder().bucket("my-bucketname").config(lifecycleConfiguration).build());
// 获取配置
LifecycleConfiguration lifecycleConfiguration1111 =
minioClient.getBucketLifecycle(
GetBucketLifecycleArgs.builder().bucket("my-bucketname").build());
List<LifecycleRule> rules1 = lifecycleConfiguration1111.rules();
for (int i = 0; i < rules1.size(); i++) {
System.out.println("Lifecycle status is " + rules1.get(i).status());
System.out.println("Lifecycle prefix is " + rules1.get(i).filter().prefix());
System.out.println("Lifecycle expiration days is " + rules1.get(i).expiration().days());
}
可以使用存储桶事件通知来监控存储桶中对象上发生的事件。
public void setBucketPolicy(SetBucketPolicyArgs args)
获取桶的通知配置:
public NotificationConfiguration getBucketNotification(GetBucketNotificationArgs args)
代码示例:
// 6. 通知配置
// Add a new SQS configuration.
NotificationConfiguration notificationConfiguration = new NotificationConfiguration();
List<QueueConfiguration> queueConfigurationList = notificationConfiguration.queueConfigurationList();
QueueConfiguration queueConfiguration = new QueueConfiguration();
queueConfiguration.setQueue("arn:minio:sqs::1:webhook");
List<EventType> eventList = new LinkedList<>();
eventList.add(EventType.OBJECT_CREATED_PUT);
eventList.add(EventType.OBJECT_CREATED_COPY);
queueConfiguration.setEvents(eventList);
queueConfiguration.setPrefixRule("images");
queueConfiguration.setSuffixRule("pg");
queueConfigurationList.add(queueConfiguration);
notificationConfiguration.setQueueConfigurationList(queueConfigurationList);
// Set updated notification configuration.
minioClient.setBucketNotification(
SetBucketNotificationArgs.builder().bucket("my-bucketname").config(notificationConfiguration).build());
System.out.println("Bucket notification is set successfully");
NotificationConfiguration minioClientBucketNotification =
minioClient.getBucketNotification(
GetBucketNotificationArgs.builder().bucket("my-bucketname").build());
System.out.println(minioClientBucketNotification);
添加存储桶策略配置。
public void setBucketPolicy(SetBucketPolicyArgs args)
获取桶的桶策略配置。
public String getBucketPolicy(GetBucketPolicyArgs args)
存储桶复制旨在将存储桶中的选定对象复制到目标存储桶,内容较多,后续补上
添加存储桶的复制配置
public void setBucketReplication(SetBucketReplicationArgs args)
获取桶的桶复制配置:
public ReplicationConfiguration getBucketReplication(GetBucketReplicationArgs args)
当为桶添加标签时,该桶上所有请求产生的计费话单里都会带上这些标签,从而可以针对话单报表做分类筛选,进行更详细的成本分析。例如:某个应用程序在运行过程会往桶里上传数据,我们可以用应用名称作为标签,设置到被使用的桶上。在分析话单时,就可以通过应用名称的标签来分析此应用的成本。
setBucketTags可以为存储桶设置标签。
public void setBucketTags(SetBucketTagsArgs args)
getBucketTags获取桶的标签。
public Tags getBucketTags(GetBucketTagsArgs args)
示例代码:
// 1. 存储桶标签
Map<String, String> map = new HashMap<>();
map.put("Project", "Project One");
map.put("User", "jsmith");
// 设置标签
minioClient.setBucketTags(SetBucketTagsArgs.builder().bucket("my-bucketname").tags(map).build());
// 查询标签
Tags bucketTags = minioClient.getBucketTags(GetBucketTagsArgs.builder().bucket("my-bucketname").build());
System.out.println(bucketTags.get().toString());
若开启了多版本控制,上传对象时,OBS自动为每个对象创建唯一的版本号。上传同名的对象将以不同的版本号同时保存在OBS中。
若未开启多版本控制,向同一个文件夹中上传同名的对象时,新上传的对象将覆盖原有的对象。
某些功能(例如版本控制、对象锁定和存储桶复制)需要使用擦除编码分布式部署 MinIO。开启了版本控制后,允许在同一密钥下保留同一对象的多个版本。
设置存储桶的版本控制配置。
public void setBucketVersioning(SetBucketVersioningArgs args)
获取存储桶的版本控制配置。
public VersioningConfiguration getBucketVersioning(GetBucketVersioningArgs args)
代码示例:
// 2. 版本配置
// 'my-bucketname'启用版本控制
minioClient.setBucketVersioning(
SetBucketVersioningArgs.builder()
.bucket("my-bucketname")
.config(new VersioningConfiguration(VersioningConfiguration.Status.ENABLED, null))
.build());
System.out.println("Bucket versioning is enabled successfully");
// 'my-bucketname'暂停版本控制
minioClient.setBucketVersioning(
SetBucketVersioningArgs.builder()
.bucket("my-bucketname")
.config(new VersioningConfiguration(VersioningConfiguration.Status.SUSPENDED, null))
.build());
System.out.println("Bucket versioning is suspended successfully");
对象锁定设置后,删除对象后,会仍然存在磁盘中。
在存储桶中设置对象锁定配置。
public void setObjectLockConfiguration(SetObjectLockConfigurationArgs args)
获取存储桶中的对象锁配置。
public ObjectLockConfiguration getObjectLockConfiguration(GetObjectLockConfigurationArgs args)
需要先设置存储桶为对象锁定模式,示例代码:
// 3. 将保留模式设置为Compliance,且持续时间为100天
// 设置锁定对象的保留模式及时限
ObjectLockConfiguration config =
new ObjectLockConfiguration(RetentionMode.COMPLIANCE, new RetentionDurationDays(100));
minioClient.setObjectLockConfiguration(
SetObjectLockConfigurationArgs.builder()
.bucket("my-bucketname-in-eu-with-object-lock")
.config(config)
.build());
System.out.println("object-lock configuration is set successfully");
// 获取锁定配置
ObjectLockConfiguration objectLockConfiguration =
minioClient.getObjectLockConfiguration(
GetObjectLockConfigurationArgs.builder()
.bucket("my-lock-enabled-bucketname")
.build());
System.out.println("Object-lock configuration of bucket");
System.out.println("Mode: " + objectLockConfiguration.mode());
System.out.println("Duration: " + objectLockConfiguration.duration());
minio提供了一些列的delete方法用于删除配置,比较简单,就不举例说明了。
public void deleteBucketEncryption(DeleteBucketEncryptionArgs args)
public void deleteBucketLifecycle(DeleteBucketLifecycleArgs args)
public void deleteBucketTags(DeleteBucketTagsArgs args)
public void deleteBucketPolicy(DeleteBucketPolicyArgs args)
public void deleteBucketReplication(DeleteBucketReplicationArgs args)
public void deleteBucketNotification(DeleteBucketNotificationArgs args)
import io.minio.*;
import io.minio.errors.*;
import io.minio.messages.Bucket;
import java.io.IOException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.util.List;
/**
* minio工具类
*
* @author wuKeFan
* @date 2023-09-08 14:08:10
*/
public class MinioUtil {
/**
* 判断桶是否存在
*/
public static boolean bucketExists(String url, String accessKey, String secretKey, String bucketName)
throws ServerException, InsufficientDataException, ErrorResponseException, IOException, NoSuchAlgorithmException, InvalidKeyException, InvalidResponseException, XmlParserException, InternalException {
MinioClient minioClient = MinioClient.builder().endpoint(url)
.credentials(accessKey, secretKey).build();
return minioClient.bucketExists(BucketExistsArgs.builder().bucket(bucketName).build());
}
/**
* 添加存储桶
*/
public static void makeBucket(String url, String accessKey, String secretKey, String bucketName, String region, boolean objectLock)
throws ServerException, InsufficientDataException, ErrorResponseException, IOException, NoSuchAlgorithmException, InvalidKeyException, InvalidResponseException, XmlParserException, InternalException {
MinioClient minioClient = MinioClient.builder().endpoint(url)
.credentials(accessKey, secretKey).build();
minioClient.makeBucket(MakeBucketArgs.builder().bucket(bucketName).region(region).objectLock(objectLock).build());
}
/**
* 指定地区添加存储桶
*/
public static void makeBucket(String url, String accessKey, String secretKey, String bucketName)
throws ServerException, InsufficientDataException, ErrorResponseException, IOException, NoSuchAlgorithmException, InvalidKeyException, InvalidResponseException, XmlParserException, InternalException {
MinioClient minioClient = MinioClient.builder().endpoint(url)
.credentials(accessKey, secretKey).build();
minioClient.makeBucket(MakeBucketArgs.builder().bucket(bucketName).build());
}
/**
* 指定地区添加存储桶并锁定对象
*/
public static void makeBucket(String url, String accessKey, String secretKey, String bucketName, String region)
throws ServerException, InsufficientDataException, ErrorResponseException, IOException, NoSuchAlgorithmException, InvalidKeyException, InvalidResponseException, XmlParserException, InternalException {
MinioClient minioClient = MinioClient.builder().endpoint(url)
.credentials(accessKey, secretKey).build();
minioClient.makeBucket(MakeBucketArgs.builder().bucket(bucketName).region(region).build());
}
/**
* 删除存储桶
*/
public static void removeBucket(String url, String accessKey, String secretKey, String bucketName)
throws ServerException, InsufficientDataException, ErrorResponseException, IOException, NoSuchAlgorithmException, InvalidKeyException, InvalidResponseException, XmlParserException, InternalException {
MinioClient minioClient = MinioClient.builder().endpoint(url)
.credentials(accessKey, secretKey).build();
minioClient.removeBucket(RemoveBucketArgs.builder().bucket(bucketName).build());
}
/**
* 设置桶公有
*/
public static void setBucketPublicPolicy(String url, String accessKey, String secretKey, String bucketName)
throws ServerException, InsufficientDataException, ErrorResponseException, IOException, NoSuchAlgorithmException, InvalidKeyException, InvalidResponseException, XmlParserException, InternalException {
MinioClient minioClient = MinioClient.builder().endpoint(url)
.credentials(accessKey, secretKey).build();
String sb = "{\"Version\":\"2012-10-17\"," +
"\"Statement\":[{\"Effect\":\"Allow\",\"Principal\":" +
"{\"AWS\":[\"*\"]},\"Action\":[\"s3:ListBucket\",\"s3:ListBucketMultipartUploads\"," +
"\"s3:GetBucketLocation\"],\"Resource\":[\"arn:aws:s3:::" + bucketName +
"\"]},{\"Effect\":\"Allow\",\"Principal\":{\"AWS\":[\"*\"]},\"Action\":[\"s3:PutObject\",\"s3:AbortMultipartUpload\",\"s3:DeleteObject\",\"s3:GetObject\",\"s3:ListMultipartUploadParts\"],\"Resource\":[\"arn:aws:s3:::" +
bucketName +
"/*\"]}]}";
minioClient.setBucketPolicy(
SetBucketPolicyArgs.builder()
.bucket(bucketName)
.config(sb)
.build());
}
/**
* 设置桶私有
*/
public static void setBucketPrivatePolicy(String url, String accessKey, String secretKey, String bucketName)
throws ServerException, InsufficientDataException, ErrorResponseException, IOException, NoSuchAlgorithmException, InvalidKeyException, InvalidResponseException, XmlParserException, InternalException {
MinioClient minioClient = MinioClient.builder().endpoint(url)
.credentials(accessKey, secretKey).build();
minioClient.setBucketPolicy(
SetBucketPolicyArgs.builder().bucket(bucketName)
.config(
"{\"Version\":\"2012-10-17\",\"Statement\":[]}"
)
.build());
}
/**
* 查询存储桶信息列表
*/
public static List<Bucket> listBuckets(String url, String accessKey, String secretKey) throws ServerException, InsufficientDataException, ErrorResponseException, IOException, NoSuchAlgorithmException, InvalidKeyException, InvalidResponseException, XmlParserException, InternalException {
MinioClient minioClient = MinioClient.builder().endpoint(url)
.credentials(accessKey, secretKey).build();
return minioClient.listBuckets();
}
}