package com.qianwen.core.oss;
|
|
import io.minio.BucketExistsArgs;
|
import io.minio.CopyObjectArgs;
|
import io.minio.CopySource;
|
import io.minio.GetObjectArgs;
|
import io.minio.GetPresignedObjectUrlArgs;
|
import io.minio.MakeBucketArgs;
|
import io.minio.MinioClient;
|
import io.minio.PutObjectArgs;
|
import io.minio.RemoveBucketArgs;
|
import io.minio.RemoveObjectArgs;
|
import io.minio.RemoveObjectsArgs;
|
import io.minio.SetBucketPolicyArgs;
|
import io.minio.StatObjectArgs;
|
import io.minio.StatObjectResponse;
|
import io.minio.http.Method;
|
import io.minio.messages.Bucket;
|
import io.minio.messages.DeleteObject;
|
import java.io.InputStream;
|
import java.math.BigDecimal;
|
import java.util.List;
|
import java.util.Optional;
|
import java.util.stream.Stream;
|
import com.qianwen.core.oss.enums.PolicyType;
|
import com.qianwen.core.oss.model.BladeFile;
|
import com.qianwen.core.oss.model.OssFile;
|
import com.qianwen.core.oss.props.OssProperties;
|
import com.qianwen.core.oss.rule.OssRule;
|
import com.qianwen.core.tool.utils.DateUtil;
|
import com.qianwen.core.tool.utils.Func;
|
import org.springframework.web.multipart.MultipartFile;
|
|
public class MinioTemplate implements OssTemplate {
|
private final MinioClient client;
|
private final OssRule ossRule;
|
private final OssProperties ossProperties;
|
|
public MinioTemplate(final MinioClient client, final OssRule ossRule, final OssProperties ossProperties) {
|
this.client = client;
|
this.ossRule = ossRule;
|
this.ossProperties = ossProperties;
|
}
|
|
@Override
|
public void makeBucket(String bucketName) {
|
try {
|
if (!this.client.bucketExists(BucketExistsArgs.builder().bucket(getBucketName(bucketName)).build())) {
|
this.client.makeBucket(MakeBucketArgs.builder().bucket(getBucketName(bucketName)).build());
|
this.client.setBucketPolicy(SetBucketPolicyArgs.builder().bucket(getBucketName(bucketName)).config(getPolicyType(getBucketName(bucketName), PolicyType.READ)).build());
|
}
|
} catch (Exception ex) {
|
throw new RuntimeException(ex);
|
}
|
}
|
|
public Bucket getBucket() {
|
return getBucket(getBucketName());
|
}
|
|
public Bucket getBucket(String bucketName) {
|
|
try {
|
Optional<Bucket> bucketOptional = this.client.listBuckets().stream().filter(bucket -> bucket.name().equals(getBucketName(bucketName))).findFirst();
|
return bucketOptional.orElse(null);
|
} catch (Exception ex) {
|
throw new RuntimeException(ex);
|
}
|
}
|
|
public List<Bucket> listBuckets() {
|
try {
|
return this.client.listBuckets();
|
} catch (Exception ex) {
|
throw new RuntimeException(ex);
|
}
|
}
|
|
@Override
|
public void removeBucket(String bucketName) {
|
try {
|
this.client.removeBucket(RemoveBucketArgs.builder().bucket(getBucketName(bucketName)).build());
|
} catch (Exception ex) {
|
throw new RuntimeException(ex);
|
}
|
}
|
|
@Override
|
public boolean bucketExists(String bucketName) {
|
try {
|
return this.client.bucketExists(BucketExistsArgs.builder().bucket(getBucketName(bucketName)).build());
|
} catch (Exception ex) {
|
throw new RuntimeException(ex);
|
}
|
}
|
|
@Override
|
public void copyFile(String bucketName, String fileName, String destBucketName) {
|
copyFile(bucketName, fileName, destBucketName, fileName);
|
}
|
|
@Override
|
public void copyFile(String bucketName, String fileName, String destBucketName, String destFileName) {
|
try {
|
this.client.copyObject(CopyObjectArgs.builder().source(CopySource.builder().bucket(getBucketName(bucketName)).object(fileName).build()).bucket(getBucketName(destBucketName)).object(destFileName).build());
|
} catch (Exception ex) {
|
throw new RuntimeException(ex);
|
}
|
}
|
|
@Override
|
public OssFile statFile(String fileName) {
|
return statFile(this.ossProperties.getBucketName(), fileName);
|
}
|
|
@Override
|
public OssFile statFile(String bucketName, String fileName) {
|
try {
|
StatObjectResponse stat = this.client.statObject(StatObjectArgs.builder().bucket(getBucketName(bucketName)).object(fileName).build());
|
OssFile ossFile = new OssFile();
|
ossFile.setName(Func.isEmpty(stat.object()) ? fileName : stat.object());
|
ossFile.setLink(fileLink(ossFile.getName()));
|
ossFile.setHash(stat.etag());
|
ossFile.setLength(stat.size());
|
ossFile.setPutTime(DateUtil.toDate(stat.lastModified().toLocalDateTime()));
|
ossFile.setContentType(stat.contentType());
|
return ossFile;
|
} catch (Exception ex) {
|
throw new RuntimeException(ex);
|
}
|
}
|
|
@Override
|
public String filePath(String fileName) {
|
return getBucketName().concat("/").concat(fileName);
|
}
|
|
@Override
|
public String filePath(String bucketName, String fileName) {
|
return getBucketName(bucketName).concat("/").concat(fileName);
|
}
|
|
@Override
|
public String fileLink(String fileName) {
|
return this.ossProperties.getEndpoint().concat("/").concat(getBucketName()).concat("/").concat(fileName);
|
}
|
|
@Override
|
public String fileLink(String bucketName, String fileName) {
|
return this.ossProperties.getEndpoint().concat("/").concat(getBucketName(bucketName)).concat("/").concat(fileName);
|
}
|
|
@Override // com.qianwen.core.oss.OssTemplate
|
public InputStream getObject(String bucketName, String fileName, Long offset, Long length) {
|
return get(bucketName, fileName, offset, length);
|
}
|
|
@Override // com.qianwen.core.oss.OssTemplate
|
public InputStream getObject(String fileName, Long offset, Long length) {
|
return get(this.ossProperties.getBucketName(), fileName, offset, length);
|
}
|
|
@Override // com.qianwen.core.oss.OssTemplate
|
public InputStream getObject(String bucketName, String fileName) {
|
return get(bucketName, fileName);
|
}
|
|
@Override // com.qianwen.core.oss.OssTemplate
|
public InputStream getObject(String fileName) {
|
return get(this.ossProperties.getBucketName(), fileName);
|
}
|
|
@Override // com.qianwen.core.oss.OssTemplate
|
public BladeFile putFile(MultipartFile file) {
|
return putFile(this.ossProperties.getBucketName(), file.getOriginalFilename(), file);
|
}
|
|
@Override // com.qianwen.core.oss.OssTemplate
|
public BladeFile putFile(String fileName, MultipartFile file) {
|
try {
|
return putFile(this.ossProperties.getBucketName(), fileName, file.getInputStream(), file.getContentType());
|
} catch (Exception ex) {
|
throw new RuntimeException(ex);
|
}
|
}
|
|
@Override // com.qianwen.core.oss.OssTemplate
|
public BladeFile putFile(String bucketName, String fileName, MultipartFile file) {
|
try {
|
return putFile(bucketName, file.getOriginalFilename(), file.getInputStream());
|
} catch (Exception ex) {
|
throw new RuntimeException(ex);
|
}
|
}
|
|
@Override // com.qianwen.core.oss.OssTemplate
|
public BladeFile putFile(String fileName, InputStream stream) {
|
return putFile(this.ossProperties.getBucketName(), fileName, stream);
|
}
|
|
@Override // com.qianwen.core.oss.OssTemplate
|
public BladeFile putFile(String bucketName, String fileName, InputStream stream) {
|
return putFile(bucketName, fileName, stream, "application/octet-stream");
|
}
|
|
public InputStream get(String bucketName, String fileName) {
|
try {
|
return this.client.getObject(GetObjectArgs.builder().bucket(getBucketName(bucketName)).object(fileName).build());
|
} catch (Exception ex) {
|
throw new RuntimeException(ex);
|
}
|
}
|
|
public InputStream get(String bucketName, String fileName, Long offset, Long length) {
|
try {
|
return this.client.getObject(GetObjectArgs.builder().bucket(getBucketName(bucketName)).object(fileName).offset(offset).length(Long.valueOf(new BigDecimal(offset.longValue()).add(new BigDecimal(length.longValue())).longValue())).build());
|
} catch (Exception ex) {
|
throw new RuntimeException(ex);
|
}
|
}
|
|
public BladeFile putFile(String bucketName, String fileName, InputStream stream, String contentType) {
|
makeBucket(bucketName);
|
String fileName2 = getFileName(fileName);
|
try {
|
this.client.putObject(PutObjectArgs.builder().bucket(getBucketName(bucketName)).object(fileName2).stream(stream, stream.available(), -1L).contentType(contentType).build());
|
BladeFile file = new BladeFile();
|
file.setOriginalName(fileName);
|
file.setName(fileName2);
|
file.setDomain(getOssHost(bucketName));
|
file.setLink(fileLink(bucketName, fileName2));
|
return file;
|
} catch (Exception ex) {
|
throw new RuntimeException(ex);
|
}
|
}
|
|
@Override // com.qianwen.core.oss.OssTemplate
|
public void removeFile(String fileName) {
|
removeFile(this.ossProperties.getBucketName(), fileName);
|
}
|
|
@Override // com.qianwen.core.oss.OssTemplate
|
public void removeFile(String bucketName, String fileName) {
|
try {
|
this.client.removeObject(RemoveObjectArgs.builder().bucket(getBucketName(bucketName)).object(fileName).build());
|
} catch (Exception ex) {
|
throw new RuntimeException(ex);
|
}
|
}
|
|
@Override // com.qianwen.core.oss.OssTemplate
|
public void removeFiles(List<String> fileNames) {
|
removeFiles(this.ossProperties.getBucketName(), fileNames);
|
}
|
|
@Override // com.qianwen.core.oss.OssTemplate
|
public void removeFiles(String bucketName, List<String> fileNames) {
|
|
try {
|
Stream<DeleteObject> stream = fileNames.stream().map(DeleteObject::new);
|
this.client.removeObjects((RemoveObjectsArgs)((RemoveObjectsArgs.Builder)RemoveObjectsArgs.builder().bucket(getBucketName(bucketName))).objects(stream::iterator).build());
|
} catch (Exception ex) {
|
throw new RuntimeException(ex);
|
}
|
|
}
|
|
private String getBucketName() {
|
return getBucketName(this.ossProperties.getBucketName());
|
}
|
|
private String getBucketName(String bucketName) {
|
return this.ossRule.bucketName(bucketName);
|
}
|
|
private String getFileName(String originalFilename) {
|
return this.ossRule.fileName(originalFilename);
|
}
|
|
public String getPresignedObjectUrl(String bucketName, String fileName, Integer expires) {
|
try {
|
return this.client.getPresignedObjectUrl(GetPresignedObjectUrlArgs.builder().method(Method.GET).bucket(getBucketName(bucketName)).object(fileName).expiry(expires.intValue()).build());
|
} catch (Exception ex) {
|
throw new RuntimeException(ex);
|
}
|
}
|
|
public String getPolicyType(PolicyType policyType) {
|
return getPolicyType(getBucketName(), policyType);
|
}
|
|
public static String getPolicyType(String bucketName, PolicyType policyType) {
|
StringBuilder builder = new StringBuilder();
|
builder.append("{\n");
|
builder.append(" \"Statement\": [\n");
|
builder.append(" {\n");
|
builder.append(" \"Action\": [\n");
|
switch (policyType) {
|
case WRITE:
|
builder.append(" \"s3:GetBucketLocation\",\n");
|
builder.append(" \"s3:ListBucketMultipartUploads\"\n");
|
break;
|
case READ_WRITE:
|
builder.append(" \"s3:GetBucketLocation\",\n");
|
builder.append(" \"s3:ListBucket\",\n");
|
builder.append(" \"s3:ListBucketMultipartUploads\"\n");
|
break;
|
default:
|
builder.append(" \"s3:GetBucketLocation\"\n");
|
break;
|
}
|
builder.append(" ],\n");
|
builder.append(" \"Effect\": \"Allow\",\n");
|
builder.append(" \"Principal\": \"*\",\n");
|
builder.append(" \"Resource\": \"arn:aws:s3:::");
|
builder.append(bucketName);
|
builder.append("\"\n");
|
builder.append(" },\n");
|
if (PolicyType.READ.equals(policyType)) {
|
builder.append(" {\n");
|
builder.append(" \"Action\": [\n");
|
builder.append(" \"s3:ListBucket\"\n");
|
builder.append(" ],\n");
|
builder.append(" \"Effect\": \"Deny\",\n");
|
builder.append(" \"Principal\": \"*\",\n");
|
builder.append(" \"Resource\": \"arn:aws:s3:::");
|
builder.append(bucketName);
|
builder.append("\"\n");
|
builder.append(" },\n");
|
}
|
builder.append(" {\n");
|
builder.append(" \"Action\": ");
|
switch (policyType) {
|
case WRITE:
|
builder.append("[\n");
|
builder.append(" \"s3:AbortMultipartUpload\",\n");
|
builder.append(" \"s3:DeleteObject\",\n");
|
builder.append(" \"s3:ListMultipartUploadParts\",\n");
|
builder.append(" \"s3:PutObject\"\n");
|
builder.append(" ],\n");
|
break;
|
case READ_WRITE:
|
builder.append("[\n");
|
builder.append(" \"s3:AbortMultipartUpload\",\n");
|
builder.append(" \"s3:DeleteObject\",\n");
|
builder.append(" \"s3:GetObject\",\n");
|
builder.append(" \"s3:ListMultipartUploadParts\",\n");
|
builder.append(" \"s3:PutObject\"\n");
|
builder.append(" ],\n");
|
break;
|
default:
|
builder.append("\"s3:GetObject\",\n");
|
break;
|
}
|
builder.append(" \"Effect\": \"Allow\",\n");
|
builder.append(" \"Principal\": \"*\",\n");
|
builder.append(" \"Resource\": \"arn:aws:s3:::");
|
builder.append(bucketName);
|
builder.append("/*\"\n");
|
builder.append(" }\n");
|
builder.append(" ],\n");
|
builder.append(" \"Version\": \"2012-10-17\"\n");
|
builder.append("}\n");
|
return builder.toString();
|
}
|
|
public String getOssHost(String bucketName) {
|
return this.ossProperties.getEndpoint() + "/" + getBucketName(bucketName);
|
}
|
|
public String getOssHost() {
|
return getOssHost(this.ossProperties.getBucketName());
|
}
|
}
|