This commit is contained in:
2025-11-28 16:23:32 +08:00
commit a9e0e16c29
826 changed files with 89805 additions and 0 deletions

70
blade-starter-oss/pom.xml Normal file
View File

@@ -0,0 +1,70 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<artifactId>BladeX-Tool</artifactId>
<groupId>org.springblade</groupId>
<version>${revision}</version>
</parent>
<artifactId>blade-starter-oss</artifactId>
<name>${project.artifactId}</name>
<version>${project.parent.version}</version>
<packaging>jar</packaging>
<dependencies>
<dependency>
<groupId>org.springblade</groupId>
<artifactId>blade-core-secure</artifactId>
</dependency>
<!--AliOss-->
<dependency>
<groupId>com.aliyun.oss</groupId>
<artifactId>aliyun-sdk-oss</artifactId>
<scope>provided</scope>
</dependency>
<!--MinIO-->
<dependency>
<groupId>io.minio</groupId>
<artifactId>minio</artifactId>
<scope>provided</scope>
</dependency>
<!--QiNiu-->
<dependency>
<groupId>com.qiniu</groupId>
<artifactId>qiniu-java-sdk</artifactId>
<scope>provided</scope>
</dependency>
<!--腾讯COS-->
<dependency>
<groupId>com.qcloud</groupId>
<artifactId>cos_api</artifactId>
<scope>provided</scope>
</dependency>
<!--华为云Obs-->
<dependency>
<groupId>com.huaweicloud</groupId>
<artifactId>esdk-obs-java</artifactId>
<scope>provided</scope>
</dependency>
<!--Aws S3-->
<dependency>
<groupId>com.amazonaws</groupId>
<artifactId>aws-java-sdk-s3</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.squareup.okhttp3</groupId>
<artifactId>okhttp</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.springblade</groupId>
<artifactId>blade-core-auto</artifactId>
<scope>provided</scope>
</dependency>
</dependencies>
</project>

View File

@@ -0,0 +1,357 @@
/**
* BladeX Commercial License Agreement
* Copyright (c) 2018-2099, https://bladex.cn. All rights reserved.
* <p>
* Use of this software is governed by the Commercial License Agreement
* obtained after purchasing a license from BladeX.
* <p>
* 1. This software is for development use only under a valid license
* from BladeX.
* <p>
* 2. Redistribution of this software's source code to any third party
* without a commercial license is strictly prohibited.
* <p>
* 3. Licensees may copyright their own code but cannot use segments
* from this software for such purposes. Copyright of this software
* remains with BladeX.
* <p>
* Using this software signifies agreement to this License, and the software
* must not be used for illegal purposes.
* <p>
* THIS SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY. The author is
* not liable for any claims arising from secondary or illegal development.
* <p>
* Author: Chill Zhuang (bladejava@qq.com)
*/
package org.springblade.core.oss;
import com.aliyun.oss.OSSClient;
import com.aliyun.oss.common.utils.BinaryUtil;
import com.aliyun.oss.model.*;
import lombok.AllArgsConstructor;
import lombok.SneakyThrows;
import org.springblade.core.oss.model.BladeFile;
import org.springblade.core.oss.model.OssFile;
import org.springblade.core.oss.props.OssProperties;
import org.springblade.core.oss.rule.OssRule;
import org.springblade.core.tool.jackson.JsonUtil;
import org.springblade.core.tool.utils.StringPool;
import org.springblade.core.tool.utils.StringUtil;
import org.springframework.util.StringUtils;
import org.springframework.web.multipart.MultipartFile;
import java.io.InputStream;
import java.nio.charset.StandardCharsets;
import java.util.Date;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
/**
* AliossTemplate
*
* @author Chill
*/
@AllArgsConstructor
public class AliossTemplate implements OssTemplate {
private final OSSClient ossClient;
private final OssProperties ossProperties;
private final OssRule ossRule;
@Override
@SneakyThrows
public void makeBucket(String bucketName) {
if (!bucketExists(bucketName)) {
ossClient.createBucket(getBucketName(bucketName));
}
}
@Override
@SneakyThrows
public void removeBucket(String bucketName) {
ossClient.deleteBucket(getBucketName(bucketName));
}
@Override
@SneakyThrows
public boolean bucketExists(String bucketName) {
return ossClient.doesBucketExist(getBucketName(bucketName));
}
@Override
@SneakyThrows
public void copyFile(String bucketName, String fileName, String destBucketName) {
ossClient.copyObject(getBucketName(bucketName), fileName, getBucketName(destBucketName), fileName);
}
@Override
@SneakyThrows
public void copyFile(String bucketName, String fileName, String destBucketName, String destFileName) {
ossClient.copyObject(getBucketName(bucketName), fileName, getBucketName(destBucketName), destFileName);
}
@Override
@SneakyThrows
public OssFile statFile(String fileName) {
return statFile(ossProperties.getBucketName(), fileName);
}
@Override
@SneakyThrows
public OssFile statFile(String bucketName, String fileName) {
ObjectMetadata stat = ossClient.getObjectMetadata(getBucketName(bucketName), fileName);
OssFile ossFile = new OssFile();
ossFile.setName(fileName);
ossFile.setLink(fileLink(ossFile.getName()));
ossFile.setHash(stat.getContentMD5());
ossFile.setLength(stat.getContentLength());
ossFile.setPutTime(stat.getLastModified());
ossFile.setContentType(stat.getContentType());
return ossFile;
}
@Override
@SneakyThrows
public String filePath(String fileName) {
return getOssHost().concat(StringPool.SLASH).concat(fileName);
}
@Override
@SneakyThrows
public String filePath(String bucketName, String fileName) {
return getOssHost(bucketName).concat(StringPool.SLASH).concat(fileName);
}
@Override
@SneakyThrows
public String fileLink(String fileName) {
return getOssHost().concat(StringPool.SLASH).concat(fileName);
}
@Override
@SneakyThrows
public String fileLink(String bucketName, String fileName) {
return getOssHost(bucketName).concat(StringPool.SLASH).concat(fileName);
}
/**
* 文件对象
*
* @param file 上传文件类
* @return
*/
@Override
@SneakyThrows
public BladeFile putFile(MultipartFile file) {
return putFile(ossProperties.getBucketName(), file.getOriginalFilename(), file);
}
/**
* @param fileName 上传文件名
* @param file 上传文件类
* @return
*/
@Override
@SneakyThrows
public BladeFile putFile(String fileName, MultipartFile file) {
return putFile(ossProperties.getBucketName(), fileName, file);
}
@Override
@SneakyThrows
public BladeFile putFile(String bucketName, String fileName, MultipartFile file) {
return putFile(bucketName, fileName, file.getInputStream());
}
@Override
@SneakyThrows
public BladeFile putFile(String fileName, InputStream stream) {
return putFile(ossProperties.getBucketName(), fileName, stream);
}
@Override
@SneakyThrows
public BladeFile putFile(String bucketName, String fileName, InputStream stream) {
return put(bucketName, stream, fileName, false);
}
@SneakyThrows
public BladeFile put(String bucketName, InputStream stream, String key, boolean cover) {
makeBucket(bucketName);
String originalName = key;
key = getFileName(key);
// 覆盖上传
if (cover) {
ossClient.putObject(getBucketName(bucketName), key, stream);
} else {
PutObjectResult response = ossClient.putObject(getBucketName(bucketName), key, stream);
int retry = 0;
int retryCount = 5;
while (StringUtils.isEmpty(response.getETag()) && retry < retryCount) {
response = ossClient.putObject(getBucketName(bucketName), key, stream);
retry++;
}
}
BladeFile file = new BladeFile();
file.setOriginalName(originalName);
file.setName(key);
file.setDomain(getOssHost(bucketName));
file.setLink(fileLink(bucketName, key));
return file;
}
@Override
@SneakyThrows
public void removeFile(String fileName) {
ossClient.deleteObject(getBucketName(), fileName);
}
@Override
@SneakyThrows
public void removeFile(String bucketName, String fileName) {
ossClient.deleteObject(getBucketName(bucketName), fileName);
}
@Override
@SneakyThrows
public void removeFiles(List<String> fileNames) {
fileNames.forEach(this::removeFile);
}
@Override
@SneakyThrows
public void removeFiles(String bucketName, List<String> fileNames) {
fileNames.forEach(fileName -> removeFile(getBucketName(bucketName), fileName));
}
/**
* 获取私有存储文件输入流
*
* @param fileName 存储桶文件名称
* @return InputStream
*/
@Override
public InputStream statFileStream(String fileName) {
return statFileStream(ossProperties.getBucketName(), fileName);
}
/**
* 获取私有存储文件输入流
*
* @param bucketName 存储桶名称
* @param fileName 存储桶文件名称
* @return InputStream
*/
@Override
public InputStream statFileStream(String bucketName, String fileName) {
OSSObject object = ossClient.getObject(getBucketName(bucketName), fileName);
return object.getObjectContent();
}
/**
* 根据规则生成存储桶名称规则
*
* @return String
*/
private String getBucketName() {
return getBucketName(ossProperties.getBucketName());
}
/**
* 根据规则生成存储桶名称规则
*
* @param bucketName 存储桶名称
* @return String
*/
private String getBucketName(String bucketName) {
return ossRule.bucketName(bucketName);
}
/**
* 根据规则生成文件名称规则
*
* @param originalFilename 原始文件名
* @return string
*/
private String getFileName(String originalFilename) {
return ossRule.fileName(originalFilename);
}
public String getUploadToken() {
return getUploadToken(ossProperties.getBucketName());
}
/**
* TODO 过期时间
* <p>
* 获取上传凭证,普通上传
*/
public String getUploadToken(String bucketName) {
// 默认过期时间2小时
return getUploadToken(bucketName, ossProperties.getArgs().get("expireTime", 3600L));
}
/**
* TODO 上传大小限制、基础路径
* <p>
* 获取上传凭证,普通上传
*/
public String getUploadToken(String bucketName, long expireTime) {
String baseDir = "upload";
long expireEndTime = System.currentTimeMillis() + expireTime * 1000;
Date expiration = new Date(expireEndTime);
PolicyConditions policyConds = new PolicyConditions();
// 默认大小限制10M
policyConds.addConditionItem(PolicyConditions.COND_CONTENT_LENGTH_RANGE, 0, ossProperties.getArgs().get("contentLengthRange", 10485760));
policyConds.addConditionItem(MatchMode.StartWith, PolicyConditions.COND_KEY, baseDir);
String postPolicy = ossClient.generatePostPolicy(expiration, policyConds);
byte[] binaryData = postPolicy.getBytes(StandardCharsets.UTF_8);
String encodedPolicy = BinaryUtil.toBase64String(binaryData);
String postSignature = ossClient.calculatePostSignature(postPolicy);
Map<String, String> respMap = new LinkedHashMap<>(16);
respMap.put("accessid", ossProperties.getAccessKey());
respMap.put("policy", encodedPolicy);
respMap.put("signature", postSignature);
respMap.put("dir", baseDir);
respMap.put("host", getOssHost(bucketName));
respMap.put("expire", String.valueOf(expireEndTime / 1000));
return JsonUtil.toJson(respMap);
}
/**
* 获取域名
*
* @param bucketName 存储桶名称
* @return String
*/
public String getOssHost(String bucketName) {
String prefix = getEndpoint().contains("https://") ? "https://" : "http://";
return prefix + getBucketName(bucketName) + StringPool.DOT + getEndpoint().replaceFirst(prefix, StringPool.EMPTY);
}
/**
* 获取域名
*
* @return String
*/
public String getOssHost() {
return getOssHost(ossProperties.getBucketName());
}
/**
* 获取服务地址
*
* @return String
*/
public String getEndpoint() {
if (StringUtil.isBlank(ossProperties.getTransformEndpoint())) {
return ossProperties.getEndpoint();
}
return ossProperties.getTransformEndpoint();
}
}

View File

@@ -0,0 +1,264 @@
package org.springblade.core.oss;
import com.obs.services.ObsClient;
import com.obs.services.model.ObjectMetadata;
import com.obs.services.model.ObsObject;
import com.obs.services.model.PutObjectResult;
import lombok.AllArgsConstructor;
import lombok.SneakyThrows;
import org.springblade.core.oss.model.BladeFile;
import org.springblade.core.oss.model.OssFile;
import org.springblade.core.oss.props.OssProperties;
import org.springblade.core.oss.rule.OssRule;
import org.springblade.core.tool.utils.StringPool;
import org.springblade.core.tool.utils.StringUtil;
import org.springframework.util.StringUtils;
import org.springframework.web.multipart.MultipartFile;
import java.io.InputStream;
import java.util.List;
/**
* @author Tonny
*/
@AllArgsConstructor
public class HuaweiObsTemplate implements OssTemplate {
private final ObsClient obsClient;
private final OssProperties ossProperties;
private final OssRule ossRule;
@Override
public void makeBucket(String bucketName) {
if (!bucketExists(bucketName)) {
obsClient.createBucket(getBucketName(bucketName));
}
}
@Override
public void removeBucket(String bucketName) {
obsClient.deleteBucket(getBucketName(bucketName));
}
@Override
public boolean bucketExists(String bucketName) {
return obsClient.headBucket(getBucketName(bucketName));
}
@Override
public void copyFile(String bucketName, String fileName, String destBucketName) {
obsClient.copyObject(getBucketName(bucketName), fileName, getBucketName(destBucketName), fileName);
}
@Override
public void copyFile(String bucketName, String fileName, String destBucketName, String destFileName) {
obsClient.copyObject(getBucketName(bucketName), fileName, getBucketName(destBucketName), destFileName);
}
@Override
public OssFile statFile(String fileName) {
return statFile(ossProperties.getBucketName(), fileName);
}
@Override
public OssFile statFile(String bucketName, String fileName) {
ObjectMetadata stat = obsClient.getObjectMetadata(getBucketName(bucketName), fileName);
OssFile ossFile = new OssFile();
ossFile.setName(fileName);
ossFile.setLink(fileLink(ossFile.getName()));
ossFile.setHash(stat.getContentMd5());
ossFile.setLength(stat.getContentLength());
ossFile.setPutTime(stat.getLastModified());
ossFile.setContentType(stat.getContentType());
return ossFile;
}
@Override
public String filePath(String fileName) {
return getOssHost(getBucketName()).concat(StringPool.SLASH).concat(fileName);
}
@Override
public String filePath(String bucketName, String fileName) {
return getOssHost(getBucketName(bucketName)).concat(StringPool.SLASH).concat(fileName);
}
@Override
public String fileLink(String fileName) {
return getOssHost().concat(StringPool.SLASH).concat(fileName);
}
@Override
public String fileLink(String bucketName, String fileName) {
return getOssHost(getBucketName(bucketName)).concat(StringPool.SLASH).concat(fileName);
}
@Override
public BladeFile putFile(MultipartFile file) {
return putFile(ossProperties.getBucketName(), file.getOriginalFilename(), file);
}
@Override
public BladeFile putFile(String fileName, MultipartFile file) {
return putFile(ossProperties.getBucketName(), fileName, file);
}
@Override
@SneakyThrows
public BladeFile putFile(String bucketName, String fileName, MultipartFile file) {
return putFile(bucketName, fileName, file.getInputStream());
}
@Override
public BladeFile putFile(String fileName, InputStream stream) {
return putFile(ossProperties.getBucketName(), fileName, stream);
}
@Override
public BladeFile putFile(String bucketName, String fileName, InputStream stream) {
return put(bucketName, stream, fileName, false);
}
@Override
public void removeFile(String fileName) {
obsClient.deleteObject(getBucketName(), fileName);
}
@Override
public void removeFile(String bucketName, String fileName) {
obsClient.deleteObject(getBucketName(bucketName), fileName);
}
@Override
public void removeFiles(List<String> fileNames) {
fileNames.forEach(this::removeFile);
}
@Override
public void removeFiles(String bucketName, List<String> fileNames) {
fileNames.forEach(fileName -> removeFile(getBucketName(bucketName), fileName));
}
/**
* 获取私有存储文件输入流
*
* @param fileName 存储桶文件名称
* @return InputStream
*/
@Override
public InputStream statFileStream(String fileName) {
return statFileStream(ossProperties.getBucketName(),fileName);
}
/**
* 获取私有存储文件输入流
*
* @param bucketName 存储桶名称
* @param fileName 存储桶文件名称
* @return InputStream
*/
@Override
public InputStream statFileStream(String bucketName, String fileName) {
ObsObject object = obsClient.getObject(getBucketName(bucketName), fileName);
return object.getObjectContent();
}
/**
* 上传文件流
*
* @param bucketName
* @param stream
* @param key
* @param cover
* @return
*/
@SneakyThrows
public BladeFile put(String bucketName, InputStream stream, String key, boolean cover) {
makeBucket(bucketName);
String originalName = key;
key = getFileName(key);
// 覆盖上传
if (cover) {
obsClient.putObject(getBucketName(bucketName), key, stream);
} else {
PutObjectResult response = obsClient.putObject(getBucketName(bucketName), key, stream);
int retry = 0;
int retryCount = 5;
while (StringUtils.isEmpty(response.getEtag()) && retry < retryCount) {
response = obsClient.putObject(getBucketName(bucketName), key, stream);
retry++;
}
}
BladeFile file = new BladeFile();
file.setOriginalName(originalName);
file.setName(key);
file.setDomain(getOssHost(bucketName));
file.setLink(fileLink(bucketName, key));
return file;
}
/**
* 根据规则生成文件名称规则
*
* @param originalFilename 原始文件名
* @return string
*/
private String getFileName(String originalFilename) {
return ossRule.fileName(originalFilename);
}
/**
* 根据规则生成存储桶名称规则 单租户
*
* @return String
*/
private String getBucketName() {
return getBucketName(ossProperties.getBucketName());
}
/**
* 根据规则生成存储桶名称规则 多租户
*
* @param bucketName 存储桶名称
* @return String
*/
private String getBucketName(String bucketName) {
return ossRule.bucketName(bucketName);
}
/**
* 获取域名
*
* @param bucketName 存储桶名称
* @return String
*/
public String getOssHost(String bucketName) {
String prefix = getEndpoint().contains("https://") ? "https://" : "http://";
return prefix + getBucketName(bucketName) + StringPool.DOT + getEndpoint().replaceFirst(prefix, StringPool.EMPTY);
}
/**
* 获取域名
*
* @return String
*/
public String getOssHost() {
return getOssHost(ossProperties.getBucketName());
}
/**
* 获取服务地址
*
* @return String
*/
public String getEndpoint() {
if (StringUtil.isBlank(ossProperties.getTransformEndpoint())) {
return ossProperties.getEndpoint();
}
return ossProperties.getTransformEndpoint();
}
}

View File

@@ -0,0 +1,478 @@
/**
* BladeX Commercial License Agreement
* Copyright (c) 2018-2099, https://bladex.cn. All rights reserved.
* <p>
* Use of this software is governed by the Commercial License Agreement
* obtained after purchasing a license from BladeX.
* <p>
* 1. This software is for development use only under a valid license
* from BladeX.
* <p>
* 2. Redistribution of this software's source code to any third party
* without a commercial license is strictly prohibited.
* <p>
* 3. Licensees may copyright their own code but cannot use segments
* from this software for such purposes. Copyright of this software
* remains with BladeX.
* <p>
* Using this software signifies agreement to this License, and the software
* must not be used for illegal purposes.
* <p>
* THIS SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY. The author is
* not liable for any claims arising from secondary or illegal development.
* <p>
* Author: Chill Zhuang (bladejava@qq.com)
*/
package org.springblade.core.oss;
import io.minio.*;
import io.minio.http.Method;
import io.minio.messages.Bucket;
import io.minio.messages.DeleteObject;
import lombok.AllArgsConstructor;
import lombok.SneakyThrows;
import org.springblade.core.oss.enums.PolicyType;
import org.springblade.core.oss.model.BladeFile;
import org.springblade.core.oss.model.OssFile;
import org.springblade.core.oss.props.OssProperties;
import org.springblade.core.oss.rule.OssRule;
import org.springblade.core.tool.utils.DateUtil;
import org.springblade.core.tool.utils.Func;
import org.springblade.core.tool.utils.StringPool;
import org.springblade.core.tool.utils.StringUtil;
import org.springframework.web.multipart.MultipartFile;
import java.io.InputStream;
import java.util.List;
import java.util.Optional;
import java.util.stream.Stream;
/**
* MinIOTemplate
*
* @author Chill
*/
@AllArgsConstructor
public class MinioTemplate implements OssTemplate {
/**
* MinIO客户端
*/
private final MinioClient client;
/**
* 存储桶命名规则
*/
private final OssRule ossRule;
/**
* 配置类
*/
private final OssProperties ossProperties;
@Override
@SneakyThrows
public void makeBucket(String bucketName) {
if (
!client.bucketExists(
BucketExistsArgs.builder().bucket(getBucketName(bucketName)).build()
)
) {
client.makeBucket(
MakeBucketArgs.builder().bucket(getBucketName(bucketName)).build()
);
client.setBucketPolicy(
SetBucketPolicyArgs.builder().bucket(getBucketName(bucketName)).config(getPolicyType(getBucketName(bucketName), PolicyType.READ)).build()
);
}
}
@SneakyThrows
public Bucket getBucket() {
return getBucket(getBucketName());
}
@SneakyThrows
public Bucket getBucket(String bucketName) {
Optional<Bucket> bucketOptional = client.listBuckets().stream().filter(bucket -> bucket.name().equals(getBucketName(bucketName))).findFirst();
return bucketOptional.orElse(null);
}
@SneakyThrows
public List<Bucket> listBuckets() {
return client.listBuckets();
}
@Override
@SneakyThrows
public void removeBucket(String bucketName) {
client.removeBucket(
RemoveBucketArgs.builder().bucket(getBucketName(bucketName)).build()
);
}
@Override
@SneakyThrows
public boolean bucketExists(String bucketName) {
return client.bucketExists(
BucketExistsArgs.builder().bucket(getBucketName(bucketName)).build()
);
}
@Override
@SneakyThrows
public void copyFile(String bucketName, String fileName, String destBucketName) {
copyFile(bucketName, fileName, destBucketName, fileName);
}
@Override
@SneakyThrows
public void copyFile(String bucketName, String fileName, String destBucketName, String destFileName) {
client.copyObject(
CopyObjectArgs.builder()
.source(CopySource.builder().bucket(getBucketName(bucketName)).object(fileName).build())
.bucket(getBucketName(destBucketName))
.object(destFileName)
.build()
);
}
@Override
@SneakyThrows
public OssFile statFile(String fileName) {
return statFile(ossProperties.getBucketName(), fileName);
}
@Override
@SneakyThrows
public OssFile statFile(String bucketName, String fileName) {
StatObjectResponse stat = 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(String.valueOf(stat.hashCode()));
ossFile.setLength(stat.size());
ossFile.setPutTime(DateUtil.toDate(stat.lastModified().toLocalDateTime()));
ossFile.setContentType(stat.contentType());
return ossFile;
}
@Override
public String filePath(String fileName) {
return getBucketName().concat(StringPool.SLASH).concat(fileName);
}
@Override
public String filePath(String bucketName, String fileName) {
return getBucketName(bucketName).concat(StringPool.SLASH).concat(fileName);
}
@Override
@SneakyThrows
public String fileLink(String fileName) {
return getEndpoint().concat(StringPool.SLASH).concat(getBucketName()).concat(StringPool.SLASH).concat(fileName);
}
@Override
@SneakyThrows
public String fileLink(String bucketName, String fileName) {
return getEndpoint().concat(StringPool.SLASH).concat(getBucketName(bucketName)).concat(StringPool.SLASH).concat(fileName);
}
@Override
@SneakyThrows
public BladeFile putFile(MultipartFile file) {
return putFile(ossProperties.getBucketName(), file.getOriginalFilename(), file);
}
@Override
@SneakyThrows
public BladeFile putFile(String fileName, MultipartFile file) {
return putFile(ossProperties.getBucketName(), fileName, file);
}
@Override
@SneakyThrows
public BladeFile putFile(String bucketName, String fileName, MultipartFile file) {
return putFile(bucketName, file.getOriginalFilename(), file.getInputStream());
}
@Override
@SneakyThrows
public BladeFile putFile(String fileName, InputStream stream) {
return putFile(ossProperties.getBucketName(), fileName, stream);
}
@Override
@SneakyThrows
public BladeFile putFile(String bucketName, String fileName, InputStream stream) {
return putFile(bucketName, fileName, stream, "application/octet-stream");
}
@SneakyThrows
public BladeFile putFile(String bucketName, String fileName, InputStream stream, String contentType) {
makeBucket(bucketName);
String originalName = fileName;
fileName = getFileName(fileName);
try {
client.putObject(
PutObjectArgs.builder()
.bucket(getBucketName(bucketName))
.object(fileName)
.stream(stream, stream.available(), -1)
.contentType(contentType)
.build()
);
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
if (stream != null) {
stream.close();
}
} catch (Exception e) {
e.printStackTrace();
}
}
BladeFile file = new BladeFile();
file.setOriginalName(originalName);
file.setName(fileName);
file.setDomain(getOssHost(bucketName));
file.setLink(fileLink(bucketName, fileName));
return file;
}
@Override
@SneakyThrows
public void removeFile(String fileName) {
removeFile(ossProperties.getBucketName(), fileName);
}
@Override
@SneakyThrows
public void removeFile(String bucketName, String fileName) {
client.removeObject(
RemoveObjectArgs.builder().bucket(getBucketName(bucketName)).object(fileName).build()
);
}
@Override
@SneakyThrows
public void removeFiles(List<String> fileNames) {
removeFiles(ossProperties.getBucketName(), fileNames);
}
@Override
@SneakyThrows
public void removeFiles(String bucketName, List<String> fileNames) {
Stream<DeleteObject> stream = fileNames.stream().map(DeleteObject::new);
client.removeObjects(RemoveObjectsArgs.builder().bucket(getBucketName(bucketName)).objects(stream::iterator).build());
}
/**
* 获取私有存储文件输入流
*
* @param fileName 存储桶文件名称
* @return InputStream
*/
@Override
public InputStream statFileStream(String fileName) {
return statFileStream(ossProperties.getBucketName(), fileName);
}
/**
* 获取私有存储文件输入流
*
* @param bucketName 存储桶名称
* @param fileName 存储桶文件名称
* @return InputStream
*/
@Override
@SneakyThrows
public InputStream statFileStream(String bucketName, String fileName) {
return client.getObject(
GetObjectArgs.builder().bucket(getBucketName(bucketName)).object(fileName).build()
);
}
/**
* 根据规则生成存储桶名称规则
*
* @return String
*/
private String getBucketName() {
return getBucketName(ossProperties.getBucketName());
}
/**
* 根据规则生成存储桶名称规则
*
* @param bucketName 存储桶名称
* @return String
*/
private String getBucketName(String bucketName) {
return ossRule.bucketName(bucketName);
}
/**
* 根据规则生成文件名称规则
*
* @param originalFilename 原始文件名
* @return string
*/
private String getFileName(String originalFilename) {
return ossRule.fileName(originalFilename);
}
/**
* 获取文件外链
*
* @param bucketName bucket名称
* @param fileName 文件名称
* @param expires 过期时间 <=7 秒级
* @return url
*/
@SneakyThrows
public String getPresignedObjectUrl(String bucketName, String fileName, Integer expires) {
return client.getPresignedObjectUrl(
GetPresignedObjectUrlArgs.builder()
.method(Method.GET)
.bucket(getBucketName(bucketName))
.object(fileName)
.expiry(expires)
.build()
);
}
/**
* 获取存储桶策略
*
* @param policyType 策略枚举
* @return String
*/
public String getPolicyType(PolicyType policyType) {
return getPolicyType(getBucketName(), policyType);
}
/**
* 获取存储桶策略
*
* @param bucketName 存储桶名称
* @param policyType 策略枚举
* @return String
*/
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();
}
/**
* 获取域名
*
* @param bucketName 存储桶名称
* @return String
*/
public String getOssHost(String bucketName) {
return getEndpoint() + StringPool.SLASH + getBucketName(bucketName);
}
/**
* 获取域名
*
* @return String
*/
public String getOssHost() {
return getOssHost(ossProperties.getBucketName());
}
/**
* 获取服务地址
*
* @return String
*/
public String getEndpoint() {
if (StringUtil.isBlank(ossProperties.getTransformEndpoint())) {
return ossProperties.getEndpoint();
}
return ossProperties.getTransformEndpoint();
}
}

View File

@@ -0,0 +1,228 @@
/**
* BladeX Commercial License Agreement
* Copyright (c) 2018-2099, https://bladex.cn. All rights reserved.
* <p>
* Use of this software is governed by the Commercial License Agreement
* obtained after purchasing a license from BladeX.
* <p>
* 1. This software is for development use only under a valid license
* from BladeX.
* <p>
* 2. Redistribution of this software's source code to any third party
* without a commercial license is strictly prohibited.
* <p>
* 3. Licensees may copyright their own code but cannot use segments
* from this software for such purposes. Copyright of this software
* remains with BladeX.
* <p>
* Using this software signifies agreement to this License, and the software
* must not be used for illegal purposes.
* <p>
* THIS SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY. The author is
* not liable for any claims arising from secondary or illegal development.
* <p>
* Author: Chill Zhuang (bladejava@qq.com)
*/
package org.springblade.core.oss;
import org.springblade.core.oss.model.BladeFile;
import org.springblade.core.oss.model.OssFile;
import org.springframework.web.multipart.MultipartFile;
import java.io.InputStream;
import java.util.List;
/**
* OssTemplate抽象API
*
* @author Chill
*/
public interface OssTemplate {
/**
* 创建 存储桶
*
* @param bucketName 存储桶名称
*/
void makeBucket(String bucketName);
/**
* 删除 存储桶
*
* @param bucketName 存储桶名称
*/
void removeBucket(String bucketName);
/**
* 存储桶是否存在
*
* @param bucketName 存储桶名称
* @return boolean
*/
boolean bucketExists(String bucketName);
/**
* 拷贝文件
*
* @param bucketName 存储桶名称
* @param fileName 存储桶文件名称
* @param destBucketName 目标存储桶名称
*/
void copyFile(String bucketName, String fileName, String destBucketName);
/**
* 拷贝文件
*
* @param bucketName 存储桶名称
* @param fileName 存储桶文件名称
* @param destBucketName 目标存储桶名称
* @param destFileName 目标存储桶文件名称
*/
void copyFile(String bucketName, String fileName, String destBucketName, String destFileName);
/**
* 获取文件信息
*
* @param fileName 存储桶文件名称
* @return InputStream
*/
OssFile statFile(String fileName);
/**
* 获取文件信息
*
* @param bucketName 存储桶名称
* @param fileName 存储桶文件名称
* @return InputStream
*/
OssFile statFile(String bucketName, String fileName);
/**
* 获取文件相对路径
*
* @param fileName 存储桶对象名称
* @return String
*/
String filePath(String fileName);
/**
* 获取文件相对路径
*
* @param bucketName 存储桶名称
* @param fileName 存储桶对象名称
* @return String
*/
String filePath(String bucketName, String fileName);
/**
* 获取文件地址
*
* @param fileName 存储桶对象名称
* @return String
*/
String fileLink(String fileName);
/**
* 获取文件地址
*
* @param bucketName 存储桶名称
* @param fileName 存储桶对象名称
* @return String
*/
String fileLink(String bucketName, String fileName);
/**
* 上传文件
*
* @param file 上传文件类
* @return BladeFile
*/
BladeFile putFile(MultipartFile file);
/**
* 上传文件
*
* @param file 上传文件类
* @param fileName 上传文件名
* @return BladeFile
*/
BladeFile putFile(String fileName, MultipartFile file);
/**
* 上传文件
*
* @param bucketName 存储桶名称
* @param fileName 上传文件名
* @param file 上传文件类
* @return BladeFile
*/
BladeFile putFile(String bucketName, String fileName, MultipartFile file);
/**
* 上传文件
*
* @param fileName 存储桶对象名称
* @param stream 文件流
* @return BladeFile
*/
BladeFile putFile(String fileName, InputStream stream);
/**
* 上传文件
*
* @param bucketName 存储桶名称
* @param fileName 存储桶对象名称
* @param stream 文件流
* @return BladeFile
*/
BladeFile putFile(String bucketName, String fileName, InputStream stream);
/**
* 删除文件
*
* @param fileName 存储桶对象名称
*/
void removeFile(String fileName);
/**
* 删除文件
*
* @param bucketName 存储桶名称
* @param fileName 存储桶对象名称
*/
void removeFile(String bucketName, String fileName);
/**
* 批量删除文件
*
* @param fileNames 存储桶对象名称集合
*/
void removeFiles(List<String> fileNames);
/**
* 批量删除文件
*
* @param bucketName 存储桶名称
* @param fileNames 存储桶对象名称集合
*/
void removeFiles(String bucketName, List<String> fileNames);
/**
* 获取私有存储文件输入流
*
* @param fileName 存储桶文件名称
* @return InputStream
*/
InputStream statFileStream(String fileName);
/**
* 获取私有存储文件输入流
*
* @param bucketName 存储桶名称
* @param fileName 存储桶文件名称
* @return InputStream
*/
InputStream statFileStream(String bucketName, String fileName);
}

View File

@@ -0,0 +1,321 @@
/**
* BladeX Commercial License Agreement
* Copyright (c) 2018-2099, https://bladex.cn. All rights reserved.
* <p>
* Use of this software is governed by the Commercial License Agreement
* obtained after purchasing a license from BladeX.
* <p>
* 1. This software is for development use only under a valid license
* from BladeX.
* <p>
* 2. Redistribution of this software's source code to any third party
* without a commercial license is strictly prohibited.
* <p>
* 3. Licensees may copyright their own code but cannot use segments
* from this software for such purposes. Copyright of this software
* remains with BladeX.
* <p>
* Using this software signifies agreement to this License, and the software
* must not be used for illegal purposes.
* <p>
* THIS SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY. The author is
* not liable for any claims arising from secondary or illegal development.
* <p>
* Author: Chill Zhuang (bladejava@qq.com)
*/
package org.springblade.core.oss;
import com.qiniu.common.Zone;
import com.qiniu.http.Response;
import com.qiniu.storage.BucketManager;
import com.qiniu.storage.UploadManager;
import com.qiniu.storage.model.FileInfo;
import com.qiniu.util.Auth;
import lombok.AllArgsConstructor;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.ResponseBody;
import org.springblade.core.oss.model.BladeFile;
import org.springblade.core.oss.model.OssFile;
import org.springblade.core.oss.props.OssProperties;
import org.springblade.core.oss.rule.OssRule;
import org.springblade.core.tool.utils.CollectionUtil;
import org.springblade.core.tool.utils.Func;
import org.springblade.core.tool.utils.StringPool;
import org.springblade.core.tool.utils.StringUtil;
import org.springframework.web.multipart.MultipartFile;
import java.io.InputStream;
import java.util.Date;
import java.util.List;
/**
* QiniuTemplate
*
* @author Chill
*/
@AllArgsConstructor
@Slf4j
public class QiniuTemplate implements OssTemplate {
private final Auth auth;
private final UploadManager uploadManager;
private final BucketManager bucketManager;
private final OssProperties ossProperties;
private final OssRule ossRule;
@Override
@SneakyThrows
public void makeBucket(String bucketName) {
if (!CollectionUtil.contains(bucketManager.buckets(), getBucketName(bucketName))) {
bucketManager.createBucket(getBucketName(bucketName), Zone.autoZone().getRegion());
}
}
@Override
public void removeBucket(String bucketName) {
}
@Override
@SneakyThrows
public boolean bucketExists(String bucketName) {
return CollectionUtil.contains(bucketManager.buckets(), getBucketName(bucketName));
}
@Override
@SneakyThrows
public void copyFile(String bucketName, String fileName, String destBucketName) {
bucketManager.copy(getBucketName(bucketName), fileName, getBucketName(destBucketName), fileName);
}
@Override
@SneakyThrows
public void copyFile(String bucketName, String fileName, String destBucketName, String destFileName) {
bucketManager.copy(getBucketName(bucketName), fileName, getBucketName(destBucketName), destFileName);
}
@Override
@SneakyThrows
public OssFile statFile(String fileName) {
return statFile(ossProperties.getBucketName(), fileName);
}
@Override
@SneakyThrows
public OssFile statFile(String bucketName, String fileName) {
FileInfo stat = bucketManager.stat(getBucketName(bucketName), fileName);
OssFile ossFile = new OssFile();
ossFile.setName(Func.isEmpty(stat.key) ? fileName : stat.key);
ossFile.setLink(fileLink(ossFile.getName()));
ossFile.setHash(stat.hash);
ossFile.setLength(stat.fsize);
ossFile.setPutTime(new Date(stat.putTime / 10000));
ossFile.setContentType(stat.mimeType);
return ossFile;
}
@Override
@SneakyThrows
public String filePath(String fileName) {
return getBucketName().concat(StringPool.SLASH).concat(fileName);
}
@Override
@SneakyThrows
public String filePath(String bucketName, String fileName) {
return getBucketName(bucketName).concat(StringPool.SLASH).concat(fileName);
}
@Override
@SneakyThrows
public String fileLink(String fileName) {
return getEndpoint().concat(StringPool.SLASH).concat(fileName);
}
@Override
@SneakyThrows
public String fileLink(String bucketName, String fileName) {
return getEndpoint().concat(StringPool.SLASH).concat(fileName);
}
@Override
@SneakyThrows
public BladeFile putFile(MultipartFile file) {
return putFile(ossProperties.getBucketName(), file.getOriginalFilename(), file);
}
@Override
@SneakyThrows
public BladeFile putFile(String fileName, MultipartFile file) {
return putFile(ossProperties.getBucketName(), fileName, file);
}
@Override
@SneakyThrows
public BladeFile putFile(String bucketName, String fileName, MultipartFile file) {
return putFile(bucketName, fileName, file.getInputStream());
}
@Override
@SneakyThrows
public BladeFile putFile(String fileName, InputStream stream) {
return putFile(ossProperties.getBucketName(), fileName, stream);
}
@Override
@SneakyThrows
public BladeFile putFile(String bucketName, String fileName, InputStream stream) {
return put(bucketName, stream, fileName, false);
}
@SneakyThrows
public BladeFile put(String bucketName, InputStream stream, String key, boolean cover) {
makeBucket(bucketName);
String originalName = key;
key = getFileName(key);
// 覆盖上传
if (cover) {
uploadManager.put(stream, key, getUploadToken(bucketName, key), null, null);
} else {
Response response = uploadManager.put(stream, key, getUploadToken(bucketName), null, null);
int retry = 0;
int retryCount = 5;
while (response.needRetry() && retry < retryCount) {
response = uploadManager.put(stream, key, getUploadToken(bucketName), null, null);
retry++;
}
}
BladeFile file = new BladeFile();
file.setOriginalName(originalName);
file.setName(key);
file.setDomain(getOssHost());
file.setLink(fileLink(bucketName, key));
return file;
}
@Override
@SneakyThrows
public void removeFile(String fileName) {
bucketManager.delete(getBucketName(), fileName);
}
@Override
@SneakyThrows
public void removeFile(String bucketName, String fileName) {
bucketManager.delete(getBucketName(bucketName), fileName);
}
@Override
@SneakyThrows
public void removeFiles(List<String> fileNames) {
fileNames.forEach(this::removeFile);
}
@Override
@SneakyThrows
public void removeFiles(String bucketName, List<String> fileNames) {
fileNames.forEach(fileName -> removeFile(getBucketName(bucketName), fileName));
}
/**
* 获取私有存储文件输入流
*
* @param fileName 存储桶文件名称
* @return InputStream
*/
@Override
public InputStream statFileStream(String fileName) {
return statFileStream(ossProperties.getBucketName(), fileName);
}
/**
* 获取文件信息
*
* @param bucketName 存储桶名称
* @param fileName 存储桶文件名称
* @return InputStream
*/
@Override
@SneakyThrows
public InputStream statFileStream(String bucketName, String fileName) {
String downloadUrl = auth.privateDownloadUrl(fileLink(fileName));
OkHttpClient client = new OkHttpClient();
Request req = new Request.Builder().url(downloadUrl).build();
okhttp3.Response resp = null;
resp = client.newCall(req).execute();
if (resp.isSuccessful()) {
ResponseBody body = resp.body();
return body.byteStream();
}
log.info("当前文件下载失败{}请检查文件是否存在或者文件是否为私有文件",fileName);
return null;
}
/**
* 根据规则生成存储桶名称规则
*
* @return String
*/
private String getBucketName() {
return getBucketName(ossProperties.getBucketName());
}
/**
* 根据规则生成存储桶名称规则
*
* @param bucketName 存储桶名称
* @return String
*/
private String getBucketName(String bucketName) {
return ossRule.bucketName(bucketName);
}
/**
* 根据规则生成文件名称规则
*
* @param originalFilename 原始文件名
* @return string
*/
private String getFileName(String originalFilename) {
return ossRule.fileName(originalFilename);
}
/**
* 获取上传凭证,普通上传
*/
public String getUploadToken(String bucketName) {
return auth.uploadToken(getBucketName(bucketName));
}
/**
* 获取上传凭证,覆盖上传
*/
private String getUploadToken(String bucketName, String key) {
return auth.uploadToken(getBucketName(bucketName), key);
}
/**
* 获取域名
*
* @return String
*/
public String getOssHost() {
return getEndpoint();
}
/**
* 获取服务地址
*
* @return String
*/
public String getEndpoint() {
if (StringUtil.isBlank(ossProperties.getTransformEndpoint())) {
return ossProperties.getEndpoint();
}
return ossProperties.getTransformEndpoint();
}
}

View File

@@ -0,0 +1,534 @@
/**
* BladeX Commercial License Agreement
* Copyright (c) 2018-2099, https://bladex.cn. All rights reserved.
* <p>
* Use of this software is governed by the Commercial License Agreement
* obtained after purchasing a license from BladeX.
* <p>
* 1. This software is for development use only under a valid license
* from BladeX.
* <p>
* 2. Redistribution of this software's source code to any third party
* without a commercial license is strictly prohibited.
* <p>
* 3. Licensees may copyright their own code but cannot use segments
* from this software for such purposes. Copyright of this software
* remains with BladeX.
* <p>
* Using this software signifies agreement to this License, and the software
* must not be used for illegal purposes.
* <p>
* THIS SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY. The author is
* not liable for any claims arising from secondary or illegal development.
* <p>
* Author: Chill Zhuang (bladejava@qq.com)
*/
package org.springblade.core.oss;
import com.amazonaws.services.s3.AmazonS3;
import com.amazonaws.services.s3.model.*;
import lombok.AllArgsConstructor;
import lombok.SneakyThrows;
import org.springblade.core.oss.enums.PolicyType;
import org.springblade.core.oss.model.BladeFile;
import org.springblade.core.oss.model.OssFile;
import org.springblade.core.oss.props.OssProperties;
import org.springblade.core.oss.rule.OssRule;
import org.springblade.core.tool.utils.Func;
import org.springblade.core.tool.utils.StringPool;
import org.springblade.core.tool.utils.StringUtil;
import org.springframework.web.multipart.MultipartFile;
import java.io.InputStream;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;
/**
* S3Template
*
* @author fanjia2
* @version 1.0.0
* @ClassName S3Template.java
* @Description Aws {@link S3Template 的代码实现}
* @createTime 2022年07月04日 11:17:00
*/
@AllArgsConstructor
public class S3Template implements OssTemplate {
/**
* S3客户端
*/
private final AmazonS3 client;
/**
* 存储桶命名规则
*/
private final OssRule ossRule;
/**
* 配置类
*/
private final OssProperties ossProperties;
/**
* 创建 存储桶
*
* @param bucketName 存储桶名称
*/
@Override
public void makeBucket(String bucketName) {
if (
!client.doesBucketExistV2(
getBucketName(bucketName)
)
) {
client.createBucket(
getBucketName(bucketName));
client.setBucketPolicy(new SetBucketPolicyRequest(getBucketName(bucketName), getPolicyType(getBucketName(bucketName), PolicyType.READ)));
}
}
@SneakyThrows
public Bucket getBucket() {
return getBucket(getBucketName());
}
@SneakyThrows
public Bucket getBucket(String bucketName) {
Optional<Bucket> bucketOptional = client.listBuckets().stream().filter(bucket -> bucket.getName().equals(getBucketName(bucketName))).findFirst();
return bucketOptional.orElse(null);
}
@SneakyThrows
public List<Bucket> listBuckets() {
return client.listBuckets();
}
/**
* 删除 存储桶
*
* @param bucketName 存储桶名称
*/
@Override
public void removeBucket(String bucketName) {
client.deleteBucket(new DeleteBucketRequest(getBucketName(bucketName)));
}
/**
* 存储桶是否存在
*
* @param bucketName 存储桶名称
* @return boolean
*/
@Override
public boolean bucketExists(String bucketName) {
return client.doesBucketExistV2(
getBucketName(bucketName));
}
/**
* 拷贝文件
*
* @param bucketName 存储桶名称
* @param fileName 存储桶文件名称
* @param destBucketName 目标存储桶名称
*/
@Override
public void copyFile(String bucketName, String fileName, String destBucketName) {
copyFile(bucketName, fileName, destBucketName, fileName);
}
/**
* 拷贝文件
*
* @param bucketName 存储桶名称
* @param fileName 存储桶文件名称
* @param destBucketName 目标存储桶名称
* @param destFileName 目标存储桶文件名称
*/
@Override
public void copyFile(String bucketName, String fileName, String destBucketName, String destFileName) {
client.copyObject(new CopyObjectRequest(getBucketName(bucketName), fileName, getBucketName(destBucketName), destFileName));
}
/**
* 获取文件信息
*
* @param fileName 存储桶文件名称
* @return InputStream
*/
@Override
public OssFile statFile(String fileName) {
return statFile(ossProperties.getBucketName(), fileName);
}
/**
* 获取文件信息
*
* @param bucketName 存储桶名称
* @param fileName 存储桶文件名称
* @return InputStream
*/
@Override
public OssFile statFile(String bucketName, String fileName) {
S3Object stat = client.getObject(new GetObjectRequest(getBucketName(bucketName), fileName));
OssFile ossFile = new OssFile();
ossFile.setName(Func.isEmpty(stat.getKey()) ? fileName : stat.getKey());
ossFile.setLink(fileLink(ossFile.getName()));
ossFile.setHash(String.valueOf(stat.hashCode()));
ossFile.setLength(stat.getObjectMetadata().getContentLength());
ossFile.setPutTime(stat.getObjectMetadata().getLastModified());
ossFile.setContentType(stat.getObjectMetadata().getContentType());
return ossFile;
}
/**
* 获取文件信息
*
* @param fileName 存储桶文件名称
* @return InputStream
*/
@Override
public InputStream statFileStream(String fileName) {
return statFileStream(getBucketName(), fileName);
}
/**
* 获取文件信息
*
* @param bucketName 存储桶名称
* @param fileName 存储桶文件名称
* @return InputStream
*/
@Override
public InputStream statFileStream(String bucketName, String fileName) {
return client.getObject(new GetObjectRequest(getBucketName(bucketName), fileName)).getObjectContent();
}
/**
* 获取文件相对路径
*
* @param fileName 存储桶对象名称
* @return String
*/
@Override
public String filePath(String fileName) {
return getBucketName().concat(StringPool.SLASH).concat(fileName);
}
/**
* 获取文件相对路径
*
* @param bucketName 存储桶名称
* @param fileName 存储桶对象名称
* @return String
*/
@Override
public String filePath(String bucketName, String fileName) {
return getBucketName(bucketName).concat(StringPool.SLASH).concat(fileName);
}
/**
* 获取文件地址
*
* @param fileName 存储桶对象名称
* @return String
*/
@Override
@SneakyThrows
public String fileLink(String fileName) {
return getEndpoint().concat(StringPool.SLASH).concat(getBucketName()).concat(StringPool.SLASH).concat(fileName);
}
/**
* 获取文件地址
*
* @param bucketName 存储桶名称
* @param fileName 存储桶对象名称
* @return String
*/
@Override
@SneakyThrows
public String fileLink(String bucketName, String fileName) {
return getEndpoint().concat(StringPool.SLASH).concat(getBucketName(bucketName)).concat(StringPool.SLASH).concat(fileName);
}
/**
* 上传文件
*
* @param file 上传文件类
* @return BladeFile
*/
@Override
@SneakyThrows
public BladeFile putFile(MultipartFile file) {
return putFile(ossProperties.getBucketName(), file.getOriginalFilename(), file);
}
/**
* 上传文件
*
* @param fileName 上传文件名
* @param file 上传文件类
* @return BladeFile
*/
@Override
@SneakyThrows
public BladeFile putFile(String fileName, MultipartFile file) {
return putFile(ossProperties.getBucketName(), fileName, file);
}
/**
* 上传文件
*
* @param bucketName 存储桶名称
* @param fileName 上传文件名
* @param file 上传文件类
* @return BladeFile
*/
@Override
@SneakyThrows
public BladeFile putFile(String bucketName, String fileName, MultipartFile file) {
return putFile(bucketName, file.getOriginalFilename(), file.getInputStream());
}
/**
* 上传文件
*
* @param fileName 存储桶对象名称
* @param stream 文件流
* @return BladeFile
*/
@Override
public BladeFile putFile(String fileName, InputStream stream) {
return putFile(ossProperties.getBucketName(), fileName, stream);
}
/**
* 上传文件
*
* @param bucketName 存储桶名称
* @param fileName 存储桶对象名称
* @param stream 文件流
* @return BladeFile
*/
@Override
public BladeFile putFile(String bucketName, String fileName, InputStream stream) {
return putFile(bucketName, fileName, stream, "application/octet-stream");
}
@SneakyThrows
public BladeFile putFile(String bucketName, String fileName, InputStream stream, String contentType) {
makeBucket(bucketName);
String originalName = fileName;
ObjectMetadata objectMetadata = new ObjectMetadata();
objectMetadata.setContentType(contentType);
fileName = getFileName(fileName);
client.putObject(new PutObjectRequest(getBucketName(bucketName), fileName, stream, objectMetadata));
BladeFile file = new BladeFile();
file.setOriginalName(originalName);
file.setName(fileName);
file.setDomain(getOssHost(bucketName));
file.setLink(fileLink(bucketName, fileName));
return file;
}
/**
* 删除文件
*
* @param fileName 存储桶对象名称
*/
@Override
public void removeFile(String fileName) {
removeFile(ossProperties.getBucketName(), fileName);
}
/**
* 删除文件
*
* @param bucketName 存储桶名称
* @param fileName 存储桶对象名称
*/
@Override
public void removeFile(String bucketName, String fileName) {
client.deleteObject(bucketName, fileName);
}
/**
* 批量删除文件
*
* @param fileNames 存储桶对象名称集合
*/
@Override
public void removeFiles(List<String> fileNames) {
removeFiles(ossProperties.getBucketName(), fileNames);
}
/**
* 批量删除文件
*
* @param bucketName 存储桶名称
* @param fileNames 存储桶对象名称集合
*/
@Override
public void removeFiles(String bucketName, List<String> fileNames) {
List<DeleteObjectsRequest.KeyVersion> keyVersions = fileNames.stream().map(DeleteObjectsRequest.KeyVersion::new).collect(Collectors.toList());
DeleteObjectsRequest deleteObjectsRequest = new DeleteObjectsRequest(getBucketName());
client.deleteObjects(deleteObjectsRequest.withKeys(keyVersions));
}
/**
* 根据规则生成存储桶名称规则
*
* @return String
*/
private String getBucketName() {
return getBucketName(ossProperties.getBucketName());
}
/**
* 根据规则生成存储桶名称规则
*
* @param bucketName 存储桶名称
* @return String
*/
private String getBucketName(String bucketName) {
return ossRule.bucketName(bucketName);
}
/**
* 根据规则生成文件名称规则
*
* @param originalFilename 原始文件名
* @return string
*/
private String getFileName(String originalFilename) {
return ossRule.fileName(originalFilename);
}
/**
* 获取存储桶策略
*
* @param bucketName 存储桶名称
* @param policyType 策略枚举
* @return String
*/
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();
}
/**
* 获取域名
*
* @param bucketName 存储桶名称
* @return String
*/
public String getOssHost(String bucketName) {
return getEndpoint() + StringPool.SLASH + getBucketName(bucketName);
}
/**
* 获取域名
*
* @return String
*/
public String getOssHost() {
return getOssHost(ossProperties.getBucketName());
}
/**
* 获取服务地址
*
* @return String
*/
public String getEndpoint() {
if (StringUtil.isBlank(ossProperties.getTransformEndpoint())) {
return ossProperties.getEndpoint();
}
return ossProperties.getTransformEndpoint();
}
}

View File

@@ -0,0 +1,315 @@
/**
* BladeX Commercial License Agreement
* Copyright (c) 2018-2099, https://bladex.cn. All rights reserved.
* <p>
* Use of this software is governed by the Commercial License Agreement
* obtained after purchasing a license from BladeX.
* <p>
* 1. This software is for development use only under a valid license
* from BladeX.
* <p>
* 2. Redistribution of this software's source code to any third party
* without a commercial license is strictly prohibited.
* <p>
* 3. Licensees may copyright their own code but cannot use segments
* from this software for such purposes. Copyright of this software
* remains with BladeX.
* <p>
* Using this software signifies agreement to this License, and the software
* must not be used for illegal purposes.
* <p>
* THIS SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY. The author is
* not liable for any claims arising from secondary or illegal development.
* <p>
* Author: Chill Zhuang (bladejava@qq.com)
*/
package org.springblade.core.oss;
import com.qcloud.cos.COSClient;
import com.qcloud.cos.model.COSObject;
import com.qcloud.cos.model.CannedAccessControlList;
import com.qcloud.cos.model.ObjectMetadata;
import com.qcloud.cos.model.PutObjectResult;
import lombok.AllArgsConstructor;
import lombok.SneakyThrows;
import org.springblade.core.oss.model.BladeFile;
import org.springblade.core.oss.model.OssFile;
import org.springblade.core.oss.props.OssProperties;
import org.springblade.core.oss.rule.OssRule;
import org.springblade.core.tool.utils.StringPool;
import org.springblade.core.tool.utils.StringUtil;
import org.springframework.util.StringUtils;
import org.springframework.web.multipart.MultipartFile;
import java.io.InputStream;
import java.util.List;
/**
* <p>
* 腾讯云 COS 操作
* </p>
*
* @author yangkai.shen
* @date Created in 2020/1/7 17:24
*/
@AllArgsConstructor
public class TencentCosTemplate implements OssTemplate {
private final COSClient cosClient;
private final OssProperties ossProperties;
private final OssRule ossRule;
@Override
@SneakyThrows
public void makeBucket(String bucketName) {
if (!bucketExists(bucketName)) {
cosClient.createBucket(getBucketName(bucketName));
// TODO: 权限是否需要修改为私有,当前为 公有读、私有写
cosClient.setBucketAcl(getBucketName(bucketName), CannedAccessControlList.PublicRead);
}
}
@Override
@SneakyThrows
public void removeBucket(String bucketName) {
cosClient.deleteBucket(getBucketName(bucketName));
}
@Override
@SneakyThrows
public boolean bucketExists(String bucketName) {
return cosClient.doesBucketExist(getBucketName(bucketName));
}
@Override
@SneakyThrows
public void copyFile(String bucketName, String fileName, String destBucketName) {
cosClient.copyObject(getBucketName(bucketName), fileName, getBucketName(destBucketName), fileName);
}
@Override
@SneakyThrows
public void copyFile(String bucketName, String fileName, String destBucketName, String destFileName) {
cosClient.copyObject(getBucketName(bucketName), fileName, getBucketName(destBucketName), destFileName);
}
@Override
@SneakyThrows
public OssFile statFile(String fileName) {
return statFile(ossProperties.getBucketName(), fileName);
}
@Override
@SneakyThrows
public OssFile statFile(String bucketName, String fileName) {
ObjectMetadata stat = cosClient.getObjectMetadata(getBucketName(bucketName), fileName);
OssFile ossFile = new OssFile();
ossFile.setName(fileName);
ossFile.setLink(fileLink(ossFile.getName()));
ossFile.setHash(stat.getContentMD5());
ossFile.setLength(stat.getContentLength());
ossFile.setPutTime(stat.getLastModified());
ossFile.setContentType(stat.getContentType());
return ossFile;
}
@Override
@SneakyThrows
public String filePath(String fileName) {
return getOssHost().concat(StringPool.SLASH).concat(fileName);
}
@Override
@SneakyThrows
public String filePath(String bucketName, String fileName) {
return getOssHost(bucketName).concat(StringPool.SLASH).concat(fileName);
}
@Override
@SneakyThrows
public String fileLink(String fileName) {
return getOssHost().concat(StringPool.SLASH).concat(fileName);
}
@Override
@SneakyThrows
public String fileLink(String bucketName, String fileName) {
return getOssHost(bucketName).concat(StringPool.SLASH).concat(fileName);
}
/**
* 文件对象
*
* @param file 上传文件类
* @return
*/
@Override
@SneakyThrows
public BladeFile putFile(MultipartFile file) {
return putFile(ossProperties.getBucketName(), file.getOriginalFilename(), file);
}
/**
* @param fileName 上传文件名
* @param file 上传文件类
* @return
*/
@Override
@SneakyThrows
public BladeFile putFile(String fileName, MultipartFile file) {
return putFile(ossProperties.getBucketName(), fileName, file);
}
@Override
@SneakyThrows
public BladeFile putFile(String bucketName, String fileName, MultipartFile file) {
return putFile(bucketName, fileName, file.getInputStream());
}
@Override
@SneakyThrows
public BladeFile putFile(String fileName, InputStream stream) {
return putFile(ossProperties.getBucketName(), fileName, stream);
}
@Override
@SneakyThrows
public BladeFile putFile(String bucketName, String fileName, InputStream stream) {
return put(bucketName, stream, fileName, false);
}
@SneakyThrows
public BladeFile put(String bucketName, InputStream stream, String key, boolean cover) {
makeBucket(bucketName);
String originalName = key;
key = getFileName(key);
ObjectMetadata objectMetadata = new ObjectMetadata();
// 覆盖上传
if (cover) {
cosClient.putObject(getBucketName(bucketName), key, stream, objectMetadata);
} else {
PutObjectResult response = cosClient.putObject(getBucketName(bucketName), key, stream, objectMetadata);
int retry = 0;
int retryCount = 5;
while (!StringUtils.hasText(response.getETag()) && retry < retryCount) {
response = cosClient.putObject(getBucketName(bucketName), key, stream, objectMetadata);
retry++;
}
}
BladeFile file = new BladeFile();
file.setOriginalName(originalName);
file.setName(key);
file.setDomain(getOssHost(bucketName));
file.setLink(fileLink(bucketName, key));
return file;
}
@Override
@SneakyThrows
public void removeFile(String fileName) {
cosClient.deleteObject(getBucketName(), fileName);
}
@Override
@SneakyThrows
public void removeFile(String bucketName, String fileName) {
cosClient.deleteObject(getBucketName(bucketName), fileName);
}
@Override
@SneakyThrows
public void removeFiles(List<String> fileNames) {
fileNames.forEach(this::removeFile);
}
@Override
@SneakyThrows
public void removeFiles(String bucketName, List<String> fileNames) {
fileNames.forEach(fileName -> removeFile(getBucketName(bucketName), fileName));
}
/**
* 获取私有存储文件输入流
*
* @param fileName 存储桶文件名称
* @return InputStream
*/
@Override
public InputStream statFileStream(String fileName) {
return statFileStream(ossProperties.getBucketName(), fileName);
}
/**
* 获取私有存储文件输入流
*
* @param bucketName 存储桶名称
* @param fileName 存储桶文件名称
* @return InputStream
*/
@Override
public InputStream statFileStream(String bucketName, String fileName) {
COSObject object = cosClient.getObject(getBucketName(bucketName), fileName);
return object.getObjectContent();
}
/**
* 根据规则生成存储桶名称规则
*
* @return String
*/
private String getBucketName() {
return getBucketName(ossProperties.getBucketName());
}
/**
* 根据规则生成存储桶名称规则
*
* @param bucketName 存储桶名称
* @return String
*/
private String getBucketName(String bucketName) {
return ossRule.bucketName(bucketName).concat(StringPool.DASH).concat(ossProperties.getAppId());
}
/**
* 根据规则生成文件名称规则
*
* @param originalFilename 原始文件名
* @return string
*/
private String getFileName(String originalFilename) {
return ossRule.fileName(originalFilename);
}
/**
* 获取域名
*
* @param bucketName 存储桶名称
* @return String
*/
public String getOssHost(String bucketName) {
String prefix = getEndpoint().contains("https://") ? "https://" : "http://";
return prefix + cosClient.getClientConfig().getEndpointBuilder().buildGeneralApiEndpoint(getBucketName(bucketName));
}
/**
* 获取域名
*
* @return String
*/
public String getOssHost() {
return getOssHost(ossProperties.getBucketName());
}
/**
* 获取服务地址
*
* @return String
*/
public String getEndpoint() {
if (StringUtil.isBlank(ossProperties.getTransformEndpoint())) {
return ossProperties.getEndpoint();
}
return ossProperties.getTransformEndpoint();
}
}

View File

@@ -0,0 +1,87 @@
/**
* BladeX Commercial License Agreement
* Copyright (c) 2018-2099, https://bladex.cn. All rights reserved.
* <p>
* Use of this software is governed by the Commercial License Agreement
* obtained after purchasing a license from BladeX.
* <p>
* 1. This software is for development use only under a valid license
* from BladeX.
* <p>
* 2. Redistribution of this software's source code to any third party
* without a commercial license is strictly prohibited.
* <p>
* 3. Licensees may copyright their own code but cannot use segments
* from this software for such purposes. Copyright of this software
* remains with BladeX.
* <p>
* Using this software signifies agreement to this License, and the software
* must not be used for illegal purposes.
* <p>
* THIS SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY. The author is
* not liable for any claims arising from secondary or illegal development.
* <p>
* Author: Chill Zhuang (bladejava@qq.com)
*/
package org.springblade.core.oss.config;
import com.aliyun.oss.ClientConfiguration;
import com.aliyun.oss.OSSClient;
import com.aliyun.oss.common.auth.CredentialsProvider;
import com.aliyun.oss.common.auth.DefaultCredentialProvider;
import lombok.AllArgsConstructor;
import org.springblade.core.oss.AliossTemplate;
import org.springblade.core.oss.props.OssProperties;
import org.springblade.core.oss.rule.OssRule;
import org.springframework.boot.autoconfigure.AutoConfiguration;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
/**
* Alioss配置类
*
* @author Chill
*/
@AllArgsConstructor
@AutoConfiguration(after = OssConfiguration.class)
@EnableConfigurationProperties(OssProperties.class)
@ConditionalOnClass({OSSClient.class})
@ConditionalOnProperty(value = "oss.name", havingValue = "alioss")
public class AliossConfiguration {
private final OssProperties ossProperties;
private final OssRule ossRule;
@Bean
@ConditionalOnMissingBean(OSSClient.class)
public OSSClient ossClient() {
// 创建ClientConfiguration。ClientConfiguration是OSSClient的配置类可配置代理、连接超时、最大连接数等参数。
ClientConfiguration conf = new ClientConfiguration();
// 设置OSSClient允许打开的最大HTTP连接数默认为1024个。
conf.setMaxConnections(1024);
// 设置Socket层传输数据的超时时间默认为50000毫秒。
conf.setSocketTimeout(50000);
// 设置建立连接的超时时间默认为50000毫秒。
conf.setConnectionTimeout(50000);
// 设置从连接池中获取连接的超时时间(单位:毫秒),默认不超时。
conf.setConnectionRequestTimeout(1000);
// 设置连接空闲超时时间。超时则关闭连接默认为60000毫秒。
conf.setIdleConnectionTime(60000);
// 设置失败请求重试次数默认为3次。
conf.setMaxErrorRetry(5);
CredentialsProvider credentialsProvider = new DefaultCredentialProvider(ossProperties.getAccessKey(), ossProperties.getSecretKey());
return new OSSClient(ossProperties.getEndpoint(), credentialsProvider, conf);
}
@Bean
@ConditionalOnBean({OSSClient.class})
@ConditionalOnMissingBean(AliossTemplate.class)
public AliossTemplate aliossTemplate(OSSClient ossClient) {
return new AliossTemplate(ossClient, ossProperties, ossRule);
}
}

View File

@@ -0,0 +1,65 @@
package org.springblade.core.oss.config;
import com.aliyun.oss.OSSClient;
import com.obs.services.ObsClient;
import com.obs.services.ObsConfiguration;
import lombok.AllArgsConstructor;
import org.springblade.core.oss.HuaweiObsTemplate;
import org.springblade.core.oss.props.OssProperties;
import org.springblade.core.oss.rule.BladeOssRule;
import org.springblade.core.oss.rule.OssRule;
import org.springframework.boot.autoconfigure.AutoConfiguration;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
/**
* @author Tonny
*/
@AllArgsConstructor
@AutoConfiguration(after = OssConfiguration.class)
@EnableConfigurationProperties(OssProperties.class)
@ConditionalOnClass({OSSClient.class})
@ConditionalOnProperty(value = "oss.name", havingValue = "huaweiobs")
public class HuaweiObsConfiguration {
private final OssProperties ossProperties;
@Bean
@ConditionalOnMissingBean(OssRule.class)
public OssRule ossRule() {
return new BladeOssRule(ossProperties.getTenantMode());
}
@Bean
@ConditionalOnMissingBean(ObsClient.class)
public ObsClient ossClient() {
// 使用可定制各参数的配置类ObsConfiguration创建OBS客户端ObsClient创建完成后不支持再次修改参数
ObsConfiguration conf = new ObsConfiguration ();
conf.setEndPoint(ossProperties.getEndpoint());
// 设置OSSClient允许打开的最大HTTP连接数默认为1024个。
conf.setMaxConnections(1024);
// 设置Socket层传输数据的超时时间默认为50000毫秒。
conf.setSocketTimeout(50000);
// 设置建立连接的超时时间默认为50000毫秒。
conf.setConnectionTimeout(50000);
// 设置从连接池中获取连接的超时时间(单位:毫秒),默认不超时。
conf.setConnectionRequestTimeout(1000);
// 设置连接空闲超时时间。超时则关闭连接默认为60000毫秒。
conf.setIdleConnectionTime(60000);
// 设置失败请求重试次数默认为3次。
conf.setMaxErrorRetry(5);
return new ObsClient(ossProperties.getAccessKey(), ossProperties.getSecretKey(), conf);
}
@Bean
@ConditionalOnMissingBean(HuaweiObsTemplate.class)
@ConditionalOnBean({ObsClient.class, OssRule.class})
public HuaweiObsTemplate huaweiobsTemplate(ObsClient obsClient, OssRule ossRule) {
return new HuaweiObsTemplate(obsClient, ossProperties, ossRule);
}
}

View File

@@ -0,0 +1,75 @@
/**
* BladeX Commercial License Agreement
* Copyright (c) 2018-2099, https://bladex.cn. All rights reserved.
* <p>
* Use of this software is governed by the Commercial License Agreement
* obtained after purchasing a license from BladeX.
* <p>
* 1. This software is for development use only under a valid license
* from BladeX.
* <p>
* 2. Redistribution of this software's source code to any third party
* without a commercial license is strictly prohibited.
* <p>
* 3. Licensees may copyright their own code but cannot use segments
* from this software for such purposes. Copyright of this software
* remains with BladeX.
* <p>
* Using this software signifies agreement to this License, and the software
* must not be used for illegal purposes.
* <p>
* THIS SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY. The author is
* not liable for any claims arising from secondary or illegal development.
* <p>
* Author: Chill Zhuang (bladejava@qq.com)
*/
package org.springblade.core.oss.config;
import io.minio.MinioClient;
import lombok.AllArgsConstructor;
import lombok.SneakyThrows;
import org.springblade.core.oss.MinioTemplate;
import org.springblade.core.oss.props.OssProperties;
import org.springblade.core.oss.rule.OssRule;
import org.springframework.boot.autoconfigure.AutoConfiguration;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
/**
* Minio配置类
*
* @author Chill
*/
@AllArgsConstructor
@AutoConfiguration(after = OssConfiguration.class)
@ConditionalOnClass({MinioClient.class})
@EnableConfigurationProperties(OssProperties.class)
@ConditionalOnProperty(value = "oss.name", havingValue = "minio")
public class MinioConfiguration {
private final OssProperties ossProperties;
private final OssRule ossRule;
@Bean
@SneakyThrows
@ConditionalOnMissingBean(MinioClient.class)
public MinioClient minioClient() {
return MinioClient.builder()
.endpoint(ossProperties.getEndpoint())
.credentials(ossProperties.getAccessKey(), ossProperties.getSecretKey())
.build();
}
@Bean
@ConditionalOnBean({MinioClient.class})
@ConditionalOnMissingBean(MinioTemplate.class)
public MinioTemplate minioTemplate(MinioClient minioClient) {
return new MinioTemplate(minioClient, ossRule, ossProperties);
}
}

View File

@@ -0,0 +1,55 @@
/**
* BladeX Commercial License Agreement
* Copyright (c) 2018-2099, https://bladex.cn. All rights reserved.
* <p>
* Use of this software is governed by the Commercial License Agreement
* obtained after purchasing a license from BladeX.
* <p>
* 1. This software is for development use only under a valid license
* from BladeX.
* <p>
* 2. Redistribution of this software's source code to any third party
* without a commercial license is strictly prohibited.
* <p>
* 3. Licensees may copyright their own code but cannot use segments
* from this software for such purposes. Copyright of this software
* remains with BladeX.
* <p>
* Using this software signifies agreement to this License, and the software
* must not be used for illegal purposes.
* <p>
* THIS SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY. The author is
* not liable for any claims arising from secondary or illegal development.
* <p>
* Author: Chill Zhuang (bladejava@qq.com)
*/
package org.springblade.core.oss.config;
import lombok.AllArgsConstructor;
import org.springblade.core.oss.props.OssProperties;
import org.springblade.core.oss.rule.BladeOssRule;
import org.springblade.core.oss.rule.OssRule;
import org.springframework.boot.autoconfigure.AutoConfiguration;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
/**
* Oss配置类
*
* @author Chill
*/
@AutoConfiguration
@AllArgsConstructor
@EnableConfigurationProperties(OssProperties.class)
public class OssConfiguration {
private final OssProperties ossProperties;
@Bean
@ConditionalOnMissingBean(OssRule.class)
public OssRule ossRule() {
return new BladeOssRule(ossProperties.getTenantMode());
}
}

View File

@@ -0,0 +1,118 @@
/**
* BladeX Commercial License Agreement
* Copyright (c) 2018-2099, https://bladex.cn. All rights reserved.
* <p>
* Use of this software is governed by the Commercial License Agreement
* obtained after purchasing a license from BladeX.
* <p>
* 1. This software is for development use only under a valid license
* from BladeX.
* <p>
* 2. Redistribution of this software's source code to any third party
* without a commercial license is strictly prohibited.
* <p>
* 3. Licensees may copyright their own code but cannot use segments
* from this software for such purposes. Copyright of this software
* remains with BladeX.
* <p>
* Using this software signifies agreement to this License, and the software
* must not be used for illegal purposes.
* <p>
* THIS SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY. The author is
* not liable for any claims arising from secondary or illegal development.
* <p>
* Author: Chill Zhuang (bladejava@qq.com)
*/
package org.springblade.core.oss.config;
import com.qiniu.storage.BucketManager;
import com.qiniu.storage.Region;
import com.qiniu.storage.UploadManager;
import com.qiniu.util.Auth;
import lombok.AllArgsConstructor;
import org.springblade.core.oss.QiniuTemplate;
import org.springblade.core.oss.props.OssProperties;
import org.springblade.core.oss.rule.OssRule;
import org.springblade.core.tool.utils.StringUtil;
import org.springframework.boot.autoconfigure.AutoConfiguration;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
/**
* Qiniu配置类
*
* @author Chill
*/
@AllArgsConstructor
@AutoConfiguration(after = OssConfiguration.class)
@ConditionalOnClass({Auth.class, UploadManager.class, BucketManager.class})
@EnableConfigurationProperties(OssProperties.class)
@ConditionalOnProperty(value = "oss.name", havingValue = "qiniu")
public class QiniuConfiguration {
private final OssProperties ossProperties;
private final OssRule ossRule;
/**
* 增加七牛云配置region的方式 目前仅支持huadong huanan huabei beimei xinjiapo
* 默认不配置采用原有的方式实现 支持配置对应的region
*/
@Bean
@ConditionalOnMissingBean(com.qiniu.storage.Configuration.class)
public com.qiniu.storage.Configuration qnConfiguration() {
Region regin = Region.autoRegion();
if (StringUtil.isNoneBlank(ossProperties.getRegion())) {
switch (ossProperties.getRegion()) {
case "huadong":
regin = Region.huadong();
break;
case "huabei":
regin = Region.huabei();
break;
case "huanan":
regin = Region.huanan();
break;
case "beimei":
regin = Region.beimei();
break;
case "xinjiapo":
regin = Region.xinjiapo();
break;
default:
regin = Region.autoRegion();
break;
}
}
return new com.qiniu.storage.Configuration(regin);
}
@Bean
@ConditionalOnMissingBean(Auth.class)
public Auth auth() {
return Auth.create(ossProperties.getAccessKey(), ossProperties.getSecretKey());
}
@Bean
@ConditionalOnBean(com.qiniu.storage.Configuration.class)
public UploadManager uploadManager(com.qiniu.storage.Configuration cfg) {
return new UploadManager(cfg);
}
@Bean
@ConditionalOnBean(com.qiniu.storage.Configuration.class)
public BucketManager bucketManager(com.qiniu.storage.Configuration cfg) {
return new BucketManager(Auth.create(ossProperties.getAccessKey(), ossProperties.getSecretKey()), cfg);
}
@Bean
@ConditionalOnBean({Auth.class, UploadManager.class, BucketManager.class})
@ConditionalOnMissingBean(QiniuTemplate.class)
public QiniuTemplate qiniuTemplate(Auth auth, UploadManager uploadManager, BucketManager bucketManager) {
return new QiniuTemplate(auth, uploadManager, bucketManager, ossProperties, ossRule);
}
}

View File

@@ -0,0 +1,97 @@
/**
* BladeX Commercial License Agreement
* Copyright (c) 2018-2099, https://bladex.cn. All rights reserved.
* <p>
* Use of this software is governed by the Commercial License Agreement
* obtained after purchasing a license from BladeX.
* <p>
* 1. This software is for development use only under a valid license
* from BladeX.
* <p>
* 2. Redistribution of this software's source code to any third party
* without a commercial license is strictly prohibited.
* <p>
* 3. Licensees may copyright their own code but cannot use segments
* from this software for such purposes. Copyright of this software
* remains with BladeX.
* <p>
* Using this software signifies agreement to this License, and the software
* must not be used for illegal purposes.
* <p>
* THIS SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY. The author is
* not liable for any claims arising from secondary or illegal development.
* <p>
* Author: Chill Zhuang (bladejava@qq.com)
*/
package org.springblade.core.oss.config;
import com.amazonaws.ClientConfiguration;
import com.amazonaws.auth.AWSCredentials;
import com.amazonaws.auth.AWSStaticCredentialsProvider;
import com.amazonaws.auth.BasicAWSCredentials;
import com.amazonaws.client.builder.AwsClientBuilder;
import com.amazonaws.regions.Regions;
import com.amazonaws.services.s3.AmazonS3;
import com.amazonaws.services.s3.AmazonS3ClientBuilder;
import lombok.AllArgsConstructor;
import lombok.SneakyThrows;
import org.springblade.core.oss.S3Template;
import org.springblade.core.oss.props.OssProperties;
import org.springblade.core.oss.rule.OssRule;
import org.springblade.core.tool.utils.StringUtil;
import org.springframework.boot.autoconfigure.AutoConfiguration;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* S3Configuration
*
* @author fanjia2
* @version 1.0.0
* @ClassName S3Configuration.java
* @Description 亚马逊 S3 配置类
* @createTime 2022年07月04日 11:19:00
*/
@Configuration(proxyBeanMethods = false)
@AllArgsConstructor
@AutoConfiguration(after = OssConfiguration.class)
@ConditionalOnClass({AmazonS3.class})
@EnableConfigurationProperties(OssProperties.class)
@ConditionalOnProperty(value = "oss.name", havingValue = "s3")
public class S3Configuration {
private final OssProperties ossProperties;
private final OssRule ossRule;
@Bean
@SneakyThrows
@ConditionalOnMissingBean(AmazonS3.class)
public AmazonS3 amazonS3() {
AWSCredentials credentials = new BasicAWSCredentials(ossProperties.getAccessKey(), ossProperties.getSecretKey());
ClientConfiguration clientConfiguration = new ClientConfiguration();
clientConfiguration.setSignerOverride("AWSS3V4SignerType");
return AmazonS3ClientBuilder
.standard()
.withEndpointConfiguration(new AwsClientBuilder.
EndpointConfiguration(ossProperties.getEndpoint(),
StringUtil.isBlank(ossProperties.getRegion()) ? Regions.DEFAULT_REGION.name() : Regions.fromName(ossProperties.getRegion()).getName()))
.withPathStyleAccessEnabled(true)
.withClientConfiguration(clientConfiguration)
.withCredentials(new AWSStaticCredentialsProvider(credentials))
.build();
}
@Bean
@ConditionalOnBean({AmazonS3.class})
@ConditionalOnMissingBean(S3Template.class)
public S3Template s3Template(AmazonS3 amazonS3) {
return new S3Template(amazonS3, ossRule, ossProperties);
}
}

View File

@@ -0,0 +1,91 @@
/**
* BladeX Commercial License Agreement
* Copyright (c) 2018-2099, https://bladex.cn. All rights reserved.
* <p>
* Use of this software is governed by the Commercial License Agreement
* obtained after purchasing a license from BladeX.
* <p>
* 1. This software is for development use only under a valid license
* from BladeX.
* <p>
* 2. Redistribution of this software's source code to any third party
* without a commercial license is strictly prohibited.
* <p>
* 3. Licensees may copyright their own code but cannot use segments
* from this software for such purposes. Copyright of this software
* remains with BladeX.
* <p>
* Using this software signifies agreement to this License, and the software
* must not be used for illegal purposes.
* <p>
* THIS SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY. The author is
* not liable for any claims arising from secondary or illegal development.
* <p>
* Author: Chill Zhuang (bladejava@qq.com)
*/
package org.springblade.core.oss.config;
import com.qcloud.cos.COSClient;
import com.qcloud.cos.ClientConfig;
import com.qcloud.cos.auth.BasicCOSCredentials;
import com.qcloud.cos.auth.COSCredentials;
import com.qcloud.cos.region.Region;
import lombok.AllArgsConstructor;
import org.springblade.core.oss.TencentCosTemplate;
import org.springblade.core.oss.props.OssProperties;
import org.springblade.core.oss.rule.OssRule;
import org.springframework.boot.autoconfigure.AutoConfiguration;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
/**
* <p>
* 腾讯云 COS 自动装配
* </p>
*
* @author yangkai.shen
* @date Created in 2020/1/7 17:24
*/
@AllArgsConstructor
@AutoConfiguration(after = OssConfiguration.class)
@ConditionalOnClass({COSClient.class})
@EnableConfigurationProperties(OssProperties.class)
@ConditionalOnProperty(value = "oss.name", havingValue = "tencentcos")
public class TencentCosConfiguration {
private final OssProperties ossProperties;
private final OssRule ossRule;
@Bean
@ConditionalOnMissingBean(COSClient.class)
public COSClient ossClient() {
// 初始化用户身份信息secretId, secretKey
COSCredentials credentials = new BasicCOSCredentials(ossProperties.getAccessKey(), ossProperties.getSecretKey());
// 设置 bucket 的区域, COS 地域的简称请参照 https://cloud.tencent.com/document/product/436/6224
Region region = new Region(ossProperties.getRegion());
// clientConfig 中包含了设置 region, https(默认 http), 超时, 代理等 set 方法, 使用可参见源码或者常见问题 Java SDK 部分。
ClientConfig clientConfig = new ClientConfig(region);
// 设置OSSClient允许打开的最大HTTP连接数默认为1024个。
clientConfig.setMaxConnectionsCount(1024);
// 设置Socket层传输数据的超时时间默认为50000毫秒。
clientConfig.setSocketTimeout(50000);
// 设置建立连接的超时时间默认为50000毫秒。
clientConfig.setConnectionTimeout(50000);
// 设置从连接池中获取连接的超时时间(单位:毫秒),默认不超时。
clientConfig.setConnectionRequestTimeout(1000);
return new COSClient(credentials, clientConfig);
}
@Bean
@ConditionalOnBean({COSClient.class})
@ConditionalOnMissingBean(TencentCosTemplate.class)
public TencentCosTemplate tencentCosTemplate(COSClient cosClient) {
return new TencentCosTemplate(cosClient, ossProperties, ossRule);
}
}

View File

@@ -0,0 +1,98 @@
/**
* BladeX Commercial License Agreement
* Copyright (c) 2018-2099, https://bladex.cn. All rights reserved.
* <p>
* Use of this software is governed by the Commercial License Agreement
* obtained after purchasing a license from BladeX.
* <p>
* 1. This software is for development use only under a valid license
* from BladeX.
* <p>
* 2. Redistribution of this software's source code to any third party
* without a commercial license is strictly prohibited.
* <p>
* 3. Licensees may copyright their own code but cannot use segments
* from this software for such purposes. Copyright of this software
* remains with BladeX.
* <p>
* Using this software signifies agreement to this License, and the software
* must not be used for illegal purposes.
* <p>
* THIS SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY. The author is
* not liable for any claims arising from secondary or illegal development.
* <p>
* Author: Chill Zhuang (bladejava@qq.com)
*/
package org.springblade.core.oss.enums;
import lombok.AllArgsConstructor;
import lombok.Getter;
/**
* Oss枚举类
*
* @author Chill
*/
@Getter
@AllArgsConstructor
public enum OssEnum {
/**
* minio
*/
MINIO("minio", 1),
/**
* qiniu
*/
QINIU("qiniu", 2),
/**
* ali
*/
ALI("alioss", 3),
/**
* tencent
*/
TENCENT("tencent", 4),
/**
* huawei
*/
HUAWEI("huawei", 5),
/**
* amazons3
*/
AMAZONS3("amazon s3", 6);
/**
* 名称
*/
final String name;
/**
* 类型
*/
final int category;
/**
* 匹配枚举值
*
* @param name 名称
* @return OssEnum
*/
public static OssEnum of(String name) {
if (name == null) {
return null;
}
OssEnum[] values = OssEnum.values();
for (OssEnum ossEnum : values) {
if (ossEnum.name.equals(name)) {
return ossEnum;
}
}
return null;
}
}

View File

@@ -0,0 +1,55 @@
/**
* BladeX Commercial License Agreement
* Copyright (c) 2018-2099, https://bladex.cn. All rights reserved.
* <p>
* Use of this software is governed by the Commercial License Agreement
* obtained after purchasing a license from BladeX.
* <p>
* 1. This software is for development use only under a valid license
* from BladeX.
* <p>
* 2. Redistribution of this software's source code to any third party
* without a commercial license is strictly prohibited.
* <p>
* 3. Licensees may copyright their own code but cannot use segments
* from this software for such purposes. Copyright of this software
* remains with BladeX.
* <p>
* Using this software signifies agreement to this License, and the software
* must not be used for illegal purposes.
* <p>
* THIS SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY. The author is
* not liable for any claims arising from secondary or illegal development.
* <p>
* Author: Chill Zhuang (bladejava@qq.com)
*/
package org.springblade.core.oss.enums;
import lombok.AllArgsConstructor;
import lombok.Getter;
/**
* Oss类型枚举
*
* @author Chill
*/
@Getter
@AllArgsConstructor
public enum OssStatusEnum {
/**
* 关闭
*/
DISABLE(1),
/**
* 启用
*/
ENABLE(2),
;
/**
* 类型编号
*/
final int num;
}

View File

@@ -0,0 +1,64 @@
/**
* BladeX Commercial License Agreement
* Copyright (c) 2018-2099, https://bladex.cn. All rights reserved.
* <p>
* Use of this software is governed by the Commercial License Agreement
* obtained after purchasing a license from BladeX.
* <p>
* 1. This software is for development use only under a valid license
* from BladeX.
* <p>
* 2. Redistribution of this software's source code to any third party
* without a commercial license is strictly prohibited.
* <p>
* 3. Licensees may copyright their own code but cannot use segments
* from this software for such purposes. Copyright of this software
* remains with BladeX.
* <p>
* Using this software signifies agreement to this License, and the software
* must not be used for illegal purposes.
* <p>
* THIS SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY. The author is
* not liable for any claims arising from secondary or illegal development.
* <p>
* Author: Chill Zhuang (bladejava@qq.com)
*/
package org.springblade.core.oss.enums;
import lombok.AllArgsConstructor;
import lombok.Getter;
/**
* minio策略配置
*
* @author SCMOX
*/
@Getter
@AllArgsConstructor
public enum PolicyType {
/**
* 只读
*/
READ("read", "只读"),
/**
* 只写
*/
WRITE("write", "只写"),
/**
* 读写
*/
READ_WRITE("read_write", "读写");
/**
* 类型
*/
private final String type;
/**
* 描述
*/
private final String policy;
}

View File

@@ -0,0 +1,57 @@
/**
* BladeX Commercial License Agreement
* Copyright (c) 2018-2099, https://bladex.cn. All rights reserved.
* <p>
* Use of this software is governed by the Commercial License Agreement
* obtained after purchasing a license from BladeX.
* <p>
* 1. This software is for development use only under a valid license
* from BladeX.
* <p>
* 2. Redistribution of this software's source code to any third party
* without a commercial license is strictly prohibited.
* <p>
* 3. Licensees may copyright their own code but cannot use segments
* from this software for such purposes. Copyright of this software
* remains with BladeX.
* <p>
* Using this software signifies agreement to this License, and the software
* must not be used for illegal purposes.
* <p>
* THIS SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY. The author is
* not liable for any claims arising from secondary or illegal development.
* <p>
* Author: Chill Zhuang (bladejava@qq.com)
*/
package org.springblade.core.oss.model;
import lombok.Data;
/**
* BladeFile
*
* @author Chill
*/
@Data
public class BladeFile {
/**
* 文件地址
*/
private String link;
/**
* 域名地址
*/
private String domain;
/**
* 文件名
*/
private String name;
/**
* 初始文件名
*/
private String originalName;
/**
* 附件表ID
*/
private Long attachId;
}

View File

@@ -0,0 +1,63 @@
/**
* BladeX Commercial License Agreement
* Copyright (c) 2018-2099, https://bladex.cn. All rights reserved.
* <p>
* Use of this software is governed by the Commercial License Agreement
* obtained after purchasing a license from BladeX.
* <p>
* 1. This software is for development use only under a valid license
* from BladeX.
* <p>
* 2. Redistribution of this software's source code to any third party
* without a commercial license is strictly prohibited.
* <p>
* 3. Licensees may copyright their own code but cannot use segments
* from this software for such purposes. Copyright of this software
* remains with BladeX.
* <p>
* Using this software signifies agreement to this License, and the software
* must not be used for illegal purposes.
* <p>
* THIS SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY. The author is
* not liable for any claims arising from secondary or illegal development.
* <p>
* Author: Chill Zhuang (bladejava@qq.com)
*/
package org.springblade.core.oss.model;
import io.minio.messages.Item;
import io.minio.messages.Owner;
import lombok.Data;
import org.springblade.core.tool.utils.DateUtil;
import java.util.Date;
/**
* MinioItem
*
* @author Chill
*/
@Data
public class MinioItem {
private String objectName;
private Date lastModified;
private String etag;
private Long size;
private String storageClass;
private Owner owner;
private boolean isDir;
private String category;
public MinioItem(Item item) {
this.objectName = item.objectName();
this.lastModified = DateUtil.toDate(item.lastModified().toLocalDateTime());
this.etag = item.etag();
this.size = item.size();
this.storageClass = item.storageClass();
this.owner = item.owner();
this.isDir = item.isDir();
this.category = isDir ? "dir" : "file";
}
}

View File

@@ -0,0 +1,63 @@
/**
* BladeX Commercial License Agreement
* Copyright (c) 2018-2099, https://bladex.cn. All rights reserved.
* <p>
* Use of this software is governed by the Commercial License Agreement
* obtained after purchasing a license from BladeX.
* <p>
* 1. This software is for development use only under a valid license
* from BladeX.
* <p>
* 2. Redistribution of this software's source code to any third party
* without a commercial license is strictly prohibited.
* <p>
* 3. Licensees may copyright their own code but cannot use segments
* from this software for such purposes. Copyright of this software
* remains with BladeX.
* <p>
* Using this software signifies agreement to this License, and the software
* must not be used for illegal purposes.
* <p>
* THIS SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY. The author is
* not liable for any claims arising from secondary or illegal development.
* <p>
* Author: Chill Zhuang (bladejava@qq.com)
*/
package org.springblade.core.oss.model;
import lombok.Data;
import java.util.Date;
/**
* OssFile
*
* @author Chill
*/
@Data
public class OssFile {
/**
* 文件地址
*/
private String link;
/**
* 文件名
*/
private String name;
/**
* 文件hash值
*/
public String hash;
/**
* 文件大小
*/
private long length;
/**
* 文件上传时间
*/
private Date putTime;
/**
* 文件contentType
*/
private String contentType;
}

View File

@@ -0,0 +1,96 @@
/**
* BladeX Commercial License Agreement
* Copyright (c) 2018-2099, https://bladex.cn. All rights reserved.
* <p>
* Use of this software is governed by the Commercial License Agreement
* obtained after purchasing a license from BladeX.
* <p>
* 1. This software is for development use only under a valid license
* from BladeX.
* <p>
* 2. Redistribution of this software's source code to any third party
* without a commercial license is strictly prohibited.
* <p>
* 3. Licensees may copyright their own code but cannot use segments
* from this software for such purposes. Copyright of this software
* remains with BladeX.
* <p>
* Using this software signifies agreement to this License, and the software
* must not be used for illegal purposes.
* <p>
* THIS SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY. The author is
* not liable for any claims arising from secondary or illegal development.
* <p>
* Author: Chill Zhuang (bladejava@qq.com)
*/
package org.springblade.core.oss.props;
import lombok.Data;
import org.springblade.core.tool.support.Kv;
import org.springframework.boot.context.properties.ConfigurationProperties;
/**
* Minio参数配置类
*
* @author Chill
*/
@Data
@ConfigurationProperties(prefix = "oss")
public class OssProperties {
/**
* 是否启用
*/
private Boolean enabled;
/**
* 对象存储名称
*/
private String name;
/**
* 是否开启租户模式
*/
private Boolean tenantMode = false;
/**
* 对象存储服务的URL
*/
private String endpoint;
/**
* 转换外网地址的URL
*/
private String transformEndpoint;
/**
* 应用ID TencentCOS需要
*/
private String appId;
/**
* 区域简称 TencentCOS/Amazon S3 需要
*/
private String region;
/**
* Access key就像用户ID可以唯一标识你的账户
*/
private String accessKey;
/**
* Secret key是你账户的密码
*/
private String secretKey;
/**
* 默认的存储桶名称
*/
private String bucketName = "bladex";
/**
* 自定义属性
*/
private Kv args;
}

View File

@@ -0,0 +1,59 @@
/**
* BladeX Commercial License Agreement
* Copyright (c) 2018-2099, https://bladex.cn. All rights reserved.
* <p>
* Use of this software is governed by the Commercial License Agreement
* obtained after purchasing a license from BladeX.
* <p>
* 1. This software is for development use only under a valid license
* from BladeX.
* <p>
* 2. Redistribution of this software's source code to any third party
* without a commercial license is strictly prohibited.
* <p>
* 3. Licensees may copyright their own code but cannot use segments
* from this software for such purposes. Copyright of this software
* remains with BladeX.
* <p>
* Using this software signifies agreement to this License, and the software
* must not be used for illegal purposes.
* <p>
* THIS SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY. The author is
* not liable for any claims arising from secondary or illegal development.
* <p>
* Author: Chill Zhuang (bladejava@qq.com)
*/
package org.springblade.core.oss.rule;
import lombok.AllArgsConstructor;
import org.springblade.core.secure.utils.AuthUtil;
import org.springblade.core.tool.utils.DateUtil;
import org.springblade.core.tool.utils.FileUtil;
import org.springblade.core.tool.utils.StringPool;
import org.springblade.core.tool.utils.StringUtil;
/**
* 默认存储桶生成规则
*
* @author Chill
*/
@AllArgsConstructor
public class BladeOssRule implements OssRule {
/**
* 租户模式
*/
private final Boolean tenantMode;
@Override
public String bucketName(String bucketName) {
String prefix = (tenantMode) ? AuthUtil.getTenantId().concat(StringPool.DASH) : StringPool.EMPTY;
return prefix + bucketName;
}
@Override
public String fileName(String originalFilename) {
return "upload" + StringPool.SLASH + DateUtil.today() + StringPool.SLASH + StringUtil.randomUUID() + StringPool.DOT + FileUtil.getFileExtension(originalFilename);
}
}

View File

@@ -0,0 +1,51 @@
/**
* BladeX Commercial License Agreement
* Copyright (c) 2018-2099, https://bladex.cn. All rights reserved.
* <p>
* Use of this software is governed by the Commercial License Agreement
* obtained after purchasing a license from BladeX.
* <p>
* 1. This software is for development use only under a valid license
* from BladeX.
* <p>
* 2. Redistribution of this software's source code to any third party
* without a commercial license is strictly prohibited.
* <p>
* 3. Licensees may copyright their own code but cannot use segments
* from this software for such purposes. Copyright of this software
* remains with BladeX.
* <p>
* Using this software signifies agreement to this License, and the software
* must not be used for illegal purposes.
* <p>
* THIS SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY. The author is
* not liable for any claims arising from secondary or illegal development.
* <p>
* Author: Chill Zhuang (bladejava@qq.com)
*/
package org.springblade.core.oss.rule;
/**
* Oss通用规则
*
* @author Chill
*/
public interface OssRule {
/**
* 获取存储桶规则
*
* @param bucketName 存储桶名称
* @return String
*/
String bucketName(String bucketName);
/**
* 获取文件名规则
*
* @param originalFilename 文件名
* @return String
*/
String fileName(String originalFilename);
}