package com.anx.minio.controller;
import io.minio.*;
import io.minio.http.Method;
import io.minio.messages.DeleteObject;
import io.minio.messages.Item;
import lombok.SneakyThrows;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Component;
import javax.annotation.PostConstruct;
import java.util.*;
import java.util.stream.Collectors;
@Component
public class MinIoUtils implements InitializingBean {
@Value("${minio.server.url}")
private String urlValue;
private static String url;
@Value("${minio.server.accessKey}")
private String accessKeyValue;
private static String accessKey;
@Value("${minio.server.secretKey}")
private String secretKeyValue;
private static String secretKey;
@Value("${minio.bucket.img}")
private String imgBucketValue;
private static String imgBucket;
@Value("${minio.bucket.chunk}")
private String chunkBucKetValue;
private static String chunkBucKet;
private static MinioClient minioClient;
public final static boolean SORT = true;
public final static boolean NOT_SORT = false;
public final static boolean DELETE_CHUNK_OBJECT = true;
public final static boolean NOT_DELETE_CHUNK_OBJECT = false;
private final static Integer DEFAULT_EXPIRY = 60;
@Override
public void afterPropertiesSet() throws Exception {
minioClient = MinioClient.builder().endpoint(url).credentials(accessKey,secretKey).build();
if (!isBucketExist(chunkBucKet)){
createBucket(chunkBucKet);
}
}
@PostConstruct
public void init(){
url = this.urlValue;
accessKey = this.accessKeyValue;
secretKey = this.secretKeyValue;
imgBucket = this.imgBucketValue;
chunkBucKet = this.chunkBucKetValue;
}
@SneakyThrows
public static boolean isBucketExist(String bucketName){
return minioClient.bucketExists(BucketExistsArgs.builder().bucket(bucketName).build());
}
@SneakyThrows
public static boolean createBucket(String bucketName){
minioClient.makeBucket(MakeBucketArgs.builder().bucket(bucketName).build());
return true;
}
@SneakyThrows
public static String getObjectUrl(String bucketName,String objectName,Integer expiry){
expiry = expiryHandle(expiry);
return minioClient.getPresignedObjectUrl(
GetPresignedObjectUrlArgs.builder()
.method(Method.GET)
.bucket(bucketName)
.object(objectName)
.expiry(expiry)
.build()
);
}
@SneakyThrows
public static String createUploadUrl(String bucketName,String objectName,Integer expiry){
expiry = expiryHandle(expiry);
return minioClient.getPresignedObjectUrl(
GetPresignedObjectUrlArgs.builder()
.method(Method.PUT)
.bucket(bucketName)
.object(objectName)
.expiry(expiry)
.build()
);
}
public static String createUploadUrl(String bucketName,String objectName){
return createUploadUrl(bucketName,objectName,DEFAULT_EXPIRY);
}
public static List<String> createUploadChunkUrlList(String bucketName,String objectMD5,Integer chunkCount){
if (null == bucketName){
bucketName = chunkBucKet;
}
if (null == objectMD5){
return null;
}
objectMD5 += "/";
if(null == chunkCount || 0 == chunkCount){
return null;
}
List<String> urlList = new ArrayList<>(chunkCount);
for (int i = 1; i <= chunkCount; i++){
String objectName = objectMD5 + i + ".chunk";
urlList.add(createUploadUrl(bucketName,objectName,DEFAULT_EXPIRY));
}
return urlList;
}
public static String createUploadChunkUrl(String bucketName,String objectMD5,Integer partNumber){
if (null == bucketName){
bucketName = chunkBucKet;
}
if (null == objectMD5){
return null;
}
objectMD5 += "/" + partNumber + ".chunk";
return createUploadUrl(bucketName,objectMD5,DEFAULT_EXPIRY);
}
@SneakyThrows
public static List<String> listObjectNames(String bucketName,String prefix,Boolean sort){
ListObjectsArgs listObjectsArgs;
if(null == prefix){
listObjectsArgs = ListObjectsArgs.builder()
.bucket(bucketName)
.recursive(true)
.build();
}else {
listObjectsArgs = ListObjectsArgs.builder()
.bucket(bucketName)
.prefix(prefix)
.recursive(true)
.build();
}
Iterable<Result<Item>> chunks = minioClient.listObjects(listObjectsArgs);
List<String> chunkPaths = new ArrayList<>();
for (Result<Item> item : chunks){
chunkPaths.add(item.get().objectName());
}
if (sort){
chunkPaths.sort(new Str2IntComparator(false));
}
return chunkPaths;
}
public static List<String> listObjectNames(String bucketName,String prefix){
return listObjectNames(bucketName, prefix, NOT_SORT);
}
public static List<String> listChunkObjectNames(String bucketName,String ObjectMd5){
if (null == bucketName){
bucketName = chunkBucKet;
}
if (null == ObjectMd5){
return null;
}
return listObjectNames(bucketName,ObjectMd5,SORT);
}
public static Map<Integer,String> mapChunkObjectNames(String bucketName, String ObjectMd5){
if (null == bucketName){
bucketName = chunkBucKet;
}
if (null == ObjectMd5){
return null;
}
List<String> chunkPaths = listObjectNames(bucketName,ObjectMd5);
if (null == chunkPaths || chunkPaths.size() == 0){
return null;
}
Map<Integer,String> chunkMap = new HashMap<>(chunkPaths.size());
for (String chunkName : chunkPaths) {
Integer partNumber = Integer.parseInt(chunkName.substring(chunkName.indexOf("/") + 1,chunkName.lastIndexOf(".")));
chunkMap.put(partNumber,chunkName);
}
return chunkMap;
}
@SneakyThrows
public static boolean removeObject(String bucketName,String objectName){
minioClient.removeObject(
RemoveObjectArgs.builder()
.bucket(bucketName)
.object(objectName)
.build()
);
return true;
}
public static boolean removeObjects(String bucketName,List<String> objectNames){
List<DeleteObject> deleteObjects = new ArrayList<>(objectNames.size());
for (String objectName : objectNames){
deleteObjects.add(new DeleteObject(objectName));
}
minioClient.removeObjects(
RemoveObjectsArgs.builder()
.bucket(bucketName)
.objects(deleteObjects)
.build()
);
return true;
}
@SneakyThrows
public static boolean composeObject(String chunkBucKetName,String composeBucketName,List<String> chunkNames,String objectName,boolean isDeleteChunkObject){
if (null == chunkBucKetName){
chunkBucKetName = chunkBucKet;
}
List<ComposeSource> sourceObjectList = new ArrayList<>(chunkNames.size());
for (String chunk : chunkNames){
sourceObjectList.add(
ComposeSource.builder()
.bucket(chunkBucKetName)
.object(chunk)
.build()
);
}
minioClient.composeObject(
ComposeObjectArgs.builder()
.bucket(composeBucketName)
.object(objectName)
.sources(sourceObjectList)
.build()
);
if(isDeleteChunkObject){
removeObjects(chunkBucKetName,chunkNames);
}
return true;
}
public static boolean composeObject(String bucketName,List<String> chunkNames,String objectName){
return composeObject(chunkBucKet,bucketName,chunkNames,objectName,NOT_DELETE_CHUNK_OBJECT);
}
public static boolean composeObject(String bucketName,List<String> chunkNames,String objectName,boolean isDeleteChunkObject){
return composeObject(chunkBucKet,bucketName,chunkNames,objectName,isDeleteChunkObject);
}
public static boolean composeObjectAndRemoveChunk(String bucketName,List<String> chunkNames,String objectName){
return composeObject(chunkBucKet,bucketName,chunkNames,objectName,DELETE_CHUNK_OBJECT);
}
private static int expiryHandle(Integer expiry){
expiry = expiry * 60;
if (expiry > 604800){
return 604800;
}
return expiry;
}
static class Str2IntComparator implements Comparator<String> {
private final boolean reverseOrder;
public Str2IntComparator(boolean reverseOrder) {
this.reverseOrder = reverseOrder;
}
@Override
public int compare(String arg0, String arg1) {
Integer intArg0 = Integer.parseInt(arg0.substring(arg0.indexOf("/") + 1,arg0.lastIndexOf(".")));
Integer intArg1 = Integer.parseInt(arg1.substring(arg1.indexOf("/") + 1,arg1.lastIndexOf(".")));
if(reverseOrder) {
return intArg1 - intArg0;
} else {
return intArg0 - intArg1;
}
}
}
}