import io.minio.*;
import io.minio.http.Method;
import io.minio.messages.*;
import lombok.AllArgsConstructor;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.multipart.MultipartFile;
import sun.misc.BASE64Decoder;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.time.ZonedDateTime;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.Optional;
import java.util.concurrent.TimeUnit;
* @author qiukl
* @create 2022/5/24 17:40
@AllArgsConstructor
@Slf4j
public class MinioTemplate {
private String endpoint;
private String accessKey;
private String secretKey;
private int partSize;
private MinioClient client;
@SneakyThrows
public MinioTemplate(String endpoint, String accessKey, String secretKey, int partSize) {
this.endpoint = endpoint;
this.accessKey = accessKey;
this.secretKey = secretKey;
this.partSize = partSize;
this.client = MinioClient.builder()
.endpoint(endpoint)
.credentials(accessKey, secretKey)
.build();
* 创建bucket
* @param bucketName bucket名称
public void createBucket(String bucketName) throws Exception {
if (!client.bucketExists(BucketExistsArgs.builder().bucket(bucketName).build())) {
client.makeBucket(MakeBucketArgs.builder().bucket(bucketName).build());
* @param bucketName
* @param days
* @param ruleName
* @throws Exception
public void setBucketExpirationByDays(String bucketName,String prefix,Integer days,String ruleName) throws Exception{
LifecycleConfiguration lifecycleConfiguration =
client.getBucketLifecycle(
GetBucketLifecycleArgs
.builder()
.bucket(bucketName)
.build());
List<LifecycleRule> rules = lifecycleConfiguration.rules();
List<LifecycleRule> rulesNew = new ArrayList<>();
rulesNew.addAll(rules);
rulesNew.add(
new LifecycleRule(
Status.ENABLED,
null,
new Expiration((ZonedDateTime) null, days, null),
new RuleFilter(prefix),
ruleName,
null,
null,
null)
LifecycleConfiguration lifecycleConfigurationNew = new LifecycleConfiguration(rulesNew);
client.setBucketLifecycle(
SetBucketLifecycleArgs
.builder()
.bucket(bucketName)
.config(lifecycleConfigurationNew)
.build()
public List<LifecycleRule> getBucketLifecycleRule(String bucketName) throws Exception{
LifecycleConfiguration lifecycleConfiguration1111 =
client.getBucketLifecycle(
GetBucketLifecycleArgs
.builder()
.bucket(bucketName)
.build());
List<LifecycleRule> rules1 = lifecycleConfiguration1111.rules();
for (LifecycleRule lifecycleRule:rules1) {
log.debug(lifecycleRule.toString());
log.debug("Lifecycle status is " + lifecycleRule.status()
+"\nLifecycle prefix is " + lifecycleRule.filter().prefix()
+"\nLifecycle expiration days is " + lifecycleRule.expiration().days());
return rules1;
* 获取全部bucket
* https://docs.minio.io/cn/java-client-api-reference.html#listBuckets
public List<Bucket> getAllBuckets() throws Exception {
return client.listBuckets();
* 根据bucketName获取信息
* @param bucketName bucket名称
public Optional<Bucket> getBucket(String bucketName) throws Exception {
return client.listBuckets().stream().filter(b -> b.name().equals(bucketName)).findFirst();
* 根据bucketName删除信息
* @param bucketName bucket名称
public void removeBucket(String bucketName) throws Exception {
client.removeBucket(RemoveBucketArgs.builder().bucket(bucketName).build());
* 分区上传文件
* @param bucketName bucket名称
* @param objectName 文件名称
* @param stream 文件流
* @param size 文件大小
public String putObject(String bucketName, String objectName, InputStream stream, Long size) throws Exception{
PutObjectArgs putObjectArgs = PutObjectArgs.builder()
.bucket(bucketName)
.object(objectName)
.stream(stream, size, partSize)
.build();
ObjectWriteResponse objectWriteResponse = client.putObject(putObjectArgs);
return objectWriteResponse.object();
* 根据文件前置查询文件
* @param bucketName bucket名称
* @param prefix 前缀
* @param recursive 是否递归查询
* @return MinioItem 列表
public List<Item> getAllObjectsByPrefix(String bucketName, String prefix, boolean recursive) throws Exception {
List<Item> objectList = new ArrayList<>();
ListObjectsArgs listObjectsArgs = ListObjectsArgs.builder()
.bucket(bucketName)
.prefix(prefix)
.recursive(recursive)
.build();
Iterable<Result<Item>> objectsIterator = client
.listObjects(listObjectsArgs);
while (objectsIterator.iterator().hasNext()) {
objectList.add(objectsIterator.iterator().next().get());
return objectList;
* 获取文件外链
* 这里的 method 方法决定最后链接是什么请求获得
* expiry 决定这个链接多久失效
* @param bucketName bucket名称
* @param objectName 文件名称
* @param duration 有效大小
* @param
* @return url
public String getObjectURL(String bucketName, String objectName,Integer duration, TimeUnit unit) throws Exception {
if (null==duration||null==unit){
duration = 7;
unit = TimeUnit.DAYS;
GetPresignedObjectUrlArgs args = GetPresignedObjectUrlArgs.builder()
.bucket(bucketName)
.method(Method.GET)
.expiry(duration, unit)
.object(objectName)
.build();
return client.getPresignedObjectUrl(args);
* 获取文件
* @param bucketName bucket名称
* @param objectName 文件名称
* @return 二进制流
public InputStream getObject(String bucketName, String objectName) throws Exception {
GetObjectArgs getObjectArgs = GetObjectArgs.builder()
.bucket(bucketName)
.object(objectName)
.build();
return client.getObject(getObjectArgs);
* 上传文件 base64
* @param bucketName bucket名称
* @param objectName 文件名称
* @param base64Str 文件base64
public String putObject(String bucketName, String objectName, String base64Str) throws Exception{
InputStream inputStream = new ByteArrayInputStream(base64Str.getBytes());
BASE64Decoder base64Decoder = new BASE64Decoder();
byte[] byt = new byte[0];
try {
byt = base64Decoder.decodeBuffer(inputStream);
} catch (IOException e) {
e.printStackTrace();
inputStream = new ByteArrayInputStream(byt);
putObject(bucketName, objectName, inputStream, Long.valueOf(byt.length));
return objectName;
* 上传文件
* @param bucketName bucket名称
* @param objectName 文件名称
* @param file 文件
* @throws Exception
public String putObject( String bucketName,String objectName, MultipartFile file) throws Exception{
this.putObject(bucketName, objectName, file.getInputStream(), file.getSize());
return objectName;
* 获取文件信息
* @param bucketName bucket名称
* @param objectName 文件名称
* @throws Exception https://docs.minio.io/cn/java-client-api-reference.html#statObject
public StatObjectResponse getObjectInfo(String bucketName, String objectName) throws Exception {
StatObjectArgs statObjectArgs = StatObjectArgs.builder()
.bucket(bucketName)
.object(objectName)
.build();
return client.statObject(statObjectArgs);
* 删除文件
* @param bucketName bucket名称
* @param objectName 文件名称
* @throws Exception https://docs.minio.io/cn/java-client-api-reference.html#removeObject
public void removeObject(String bucketName, String objectName) throws Exception {
RemoveObjectArgs removeObjectArgs = RemoveObjectArgs.builder()
.bucket(bucketName)
.object(objectName)
.build();
client.removeObject(removeObjectArgs);
* 根据文件名返回对应contentType
* @param objectName
* @return
private String getContentType(String objectName) {
return null;
* 获取直传链接
* @param bucketName bucket名称
* @param objectName 文件名称
* @throws Exception
public String presignedPutObject( String bucketName,String objectName) throws Exception{
GetPresignedObjectUrlArgs getPresignedObjectUrlArgs = GetPresignedObjectUrlArgs.builder()
.method(Method.PUT)
.bucket(bucketName)
.object(objectName)
.expiry(7, TimeUnit.DAYS)
.build();
return client.getPresignedObjectUrl(getPresignedObjectUrlArgs);
* 合并文件
* @param bucketName
* @param chunkNames
* @param targetObjectName
* @return
* @throws Exception
public String composeObject(String bucketName, List<String> chunkNames, String targetObjectName) throws Exception{
List<ComposeSource> sources = new ArrayList<>(chunkNames.size());
for (String chunkName : chunkNames) {
ComposeSource composeSource = ComposeSource.builder()
.bucket(bucketName)
.object(chunkName)
.build();
sources.add(composeSource);
ComposeObjectArgs composeObjectArgs = ComposeObjectArgs.builder()
.bucket(bucketName)
.sources(sources)
.object(targetObjectName)
.build();
ObjectWriteResponse objectWriteResponse = client.composeObject(composeObjectArgs);
return objectWriteResponse.object();
MinIO Java Client SDK提供简单的API来访问任何与Amazon S3兼容的对象存储服务。官方demo: https://github.com/minio/minio-java
官方文档:https://docs.min.io/docs/java-client-api-reference.html
新版 MinIO和旧版在 API使用上还是有一定的区别,比如:新版 MinIO采用 Builder构建者模式来构造 MinioClient对象。所以,官方demo仅供参考,尽量查看英文官方文档。
minio基础知识介绍
文章目录minio基础知识介绍1 概述1.1 特性1.2 部署运行模式2 存储机制2.1 纠错码2.2 RS code编码数据恢复原理2.3 校验和3 minio多租户和多用户3.1 多租户3.2 多用户4 minio集群及扩容4.1 minio集群架构4.2 minio集群的数据对象存储4.3 MinIO集群扩容方式5 总结
minio为开源的高可用分部署对象存储服务组件,已经提供了分布式部署的解决方案,实现高可靠、高可用的资源存储,MinIO以极简主义为指导进行设计,追求极致的
npm install --save hexo-deployer-oss-aliyun
# https://oss.console.aliyun.com/bucket/oss-us-west-1/f9a329b03
deploy :
type : aliyun-oss
region : <Region> # oss-us-west-1
bucket : <Bucket> # f9a329b03
accessKeyId : <Aliyun>
accessKeySecret : <Aliyun>
hexo d
官方的git代码库,给的example是5.x版本案例,并且官方使用npm run build-dist打不了包,可能代码太过来老旧;
案例中OSS.wrapper属于6.x以下版本,已改为OSS方式,采用实际子账户进行分片上传,发现没有问题;
操作步骤:
1,npm install
2,cd example
3,npm install
4,npm run server
5,npm run dev
别忘记配置example/server/config.js的accessId和accessKey以及其他,配置完成后即可使用,跨域问题,可以使用谷歌浏览器,去除跨域限制即可;
打包方式,在根目录运行:
npm run build-dist 会在dist文件夹下面生成两个文件,压缩的和未压缩的
根据官方定义:
MinIO 是在 Apache License v2.0 下发布的对象存储服务器。 它与 Amazon S3 云存储服务兼容。 它最适合存储非结构化数据,如照片,视频,日志文件,备份和容器/ VM 映像。 对象的大小可以从几 KB 到最大 5TB。
MinIO 服务器足够轻,可以与应用程序堆栈捆绑在一起,类似于 NodeJS,Redis 和 MySQL。...