支持s3 storage
This commit is contained in:
parent
c321b41ad7
commit
9dc5708d04
12
pom.xml
12
pom.xml
@ -175,6 +175,18 @@
|
|||||||
<version>3.17.4</version>
|
<version>3.17.4</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
|
<!-- S3对象存储 -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.amazonaws</groupId>
|
||||||
|
<artifactId>aws-java-sdk-core</artifactId>
|
||||||
|
<version>1.11.24</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.amazonaws</groupId>
|
||||||
|
<artifactId>aws-java-sdk-s3</artifactId>
|
||||||
|
<version>1.11.24</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
<!-- 阿里云人脸识别 -->
|
<!-- 阿里云人脸识别 -->
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.aliyun</groupId>
|
<groupId>com.aliyun</groupId>
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
package com.ycwl.basic.storage;
|
package com.ycwl.basic.storage;
|
||||||
|
|
||||||
import com.ycwl.basic.storage.adapters.AliOssAdapter;
|
import com.ycwl.basic.storage.adapters.AliOssAdapter;
|
||||||
|
import com.ycwl.basic.storage.adapters.AwsOssAdapter;
|
||||||
import com.ycwl.basic.storage.adapters.IStorageAdapter;
|
import com.ycwl.basic.storage.adapters.IStorageAdapter;
|
||||||
import com.ycwl.basic.storage.adapters.LocalStorageAdapter;
|
import com.ycwl.basic.storage.adapters.LocalStorageAdapter;
|
||||||
import com.ycwl.basic.storage.entity.StorageConfig;
|
import com.ycwl.basic.storage.entity.StorageConfig;
|
||||||
@ -23,6 +24,8 @@ public class StorageFactory {
|
|||||||
switch (storageType) {
|
switch (storageType) {
|
||||||
case LOCAL:
|
case LOCAL:
|
||||||
return new LocalStorageAdapter();
|
return new LocalStorageAdapter();
|
||||||
|
case AWS_OSS:
|
||||||
|
return new AwsOssAdapter();
|
||||||
case ALI_OSS:
|
case ALI_OSS:
|
||||||
return new AliOssAdapter();
|
return new AliOssAdapter();
|
||||||
default:
|
default:
|
||||||
|
196
src/main/java/com/ycwl/basic/storage/adapters/AwsOssAdapter.java
Normal file
196
src/main/java/com/ycwl/basic/storage/adapters/AwsOssAdapter.java
Normal file
@ -0,0 +1,196 @@
|
|||||||
|
package com.ycwl.basic.storage.adapters;
|
||||||
|
|
||||||
|
import com.amazonaws.ClientConfiguration;
|
||||||
|
import com.amazonaws.HttpMethod;
|
||||||
|
import com.amazonaws.Protocol;
|
||||||
|
import com.amazonaws.auth.BasicAWSCredentials;
|
||||||
|
import com.amazonaws.services.s3.AmazonS3;
|
||||||
|
import com.amazonaws.services.s3.AmazonS3Client;
|
||||||
|
import com.amazonaws.services.s3.AmazonS3ClientBuilder;
|
||||||
|
import com.amazonaws.services.s3.S3ClientOptions;
|
||||||
|
import com.amazonaws.services.s3.model.*;
|
||||||
|
import com.ycwl.basic.storage.entity.AwsOssStorageConfig;
|
||||||
|
import com.ycwl.basic.storage.entity.StorageConfig;
|
||||||
|
import com.ycwl.basic.storage.entity.StorageFileObject;
|
||||||
|
import com.ycwl.basic.storage.exceptions.StorageConfigException;
|
||||||
|
import com.ycwl.basic.storage.exceptions.StorageException;
|
||||||
|
import com.ycwl.basic.storage.exceptions.UploadFileFailedException;
|
||||||
|
import com.ycwl.basic.storage.utils.StorageUtil;
|
||||||
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.net.URL;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
public class AwsOssAdapter extends AStorageAdapter {
|
||||||
|
private AwsOssStorageConfig config;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void loadConfig(Map<String, String> _config) {
|
||||||
|
AwsOssStorageConfig config = new AwsOssStorageConfig();
|
||||||
|
config.setAccessKeyId(_config.get("accessKeyId"));
|
||||||
|
config.setAccessKeySecret(_config.get("accessKeySecret"));
|
||||||
|
config.setBucketName(_config.get("bucketName"));
|
||||||
|
config.setEndpoint(_config.get("endpoint"));
|
||||||
|
config.setRegion(_config.get("region"));
|
||||||
|
config.setUrl(_config.get("url"));
|
||||||
|
config.setPrefix(_config.get("prefix"));
|
||||||
|
config.checkEverythingOK();
|
||||||
|
this.config = config;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setConfig(StorageConfig config) {
|
||||||
|
if (config == null) {
|
||||||
|
throw new StorageConfigException("配置为空");
|
||||||
|
}
|
||||||
|
if (config instanceof AwsOssStorageConfig) {
|
||||||
|
this.config = (AwsOssStorageConfig) config;
|
||||||
|
} else {
|
||||||
|
throw new StorageConfigException("配置类型错误,传入的类为:" + config.getClass().getName());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String uploadFile(InputStream inputStream, String... path) {
|
||||||
|
if (inputStream == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
String fullPath = buildPath(path);
|
||||||
|
AmazonS3 s3Client = getS3Client();
|
||||||
|
try {
|
||||||
|
ObjectMetadata metadata = new ObjectMetadata();
|
||||||
|
s3Client.putObject(new PutObjectRequest(config.getBucketName(), fullPath, inputStream, metadata));
|
||||||
|
return getUrl(path);
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new UploadFileFailedException("上传文件失败:" + e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean deleteFile(String... path) {
|
||||||
|
AmazonS3 s3Client = getS3Client();
|
||||||
|
try {
|
||||||
|
s3Client.deleteObject(config.getBucketName(), buildPath(path));
|
||||||
|
return true;
|
||||||
|
} catch (Exception e) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getUrl(String... path) {
|
||||||
|
return config.getUrl() + "/" + buildPath(path);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getUrlForDownload(Date expireDate, String... path) {
|
||||||
|
AmazonS3 s3Client = getS3Client();
|
||||||
|
URL url = s3Client.generatePresignedUrl(config.getBucketName(), buildPath(path), expireDate);
|
||||||
|
return url.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getUrlForUpload(Date expireDate, String contentType, String... path) {
|
||||||
|
AmazonS3 s3Client = getS3Client();
|
||||||
|
GeneratePresignedUrlRequest request = new GeneratePresignedUrlRequest(config.getBucketName(), buildPath(path));
|
||||||
|
request.setMethod(HttpMethod.PUT);
|
||||||
|
if (StringUtils.isNotBlank(contentType)) {
|
||||||
|
request.setContentType(contentType);
|
||||||
|
}
|
||||||
|
request.setExpiration(expireDate);
|
||||||
|
URL url = s3Client.generatePresignedUrl(request);
|
||||||
|
return url.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<StorageFileObject> listDir(String... path) {
|
||||||
|
AmazonS3 s3Client = getS3Client();
|
||||||
|
ListObjectsV2Request listObjectsV2Request = new ListObjectsV2Request()
|
||||||
|
.withBucketName(config.getBucketName())
|
||||||
|
.withPrefix(buildPath(path) + "/")
|
||||||
|
.withMaxKeys(1000);
|
||||||
|
boolean isTruncated = true;
|
||||||
|
String continuationToken = null;
|
||||||
|
List<S3ObjectSummary> objectList = new ArrayList<>();
|
||||||
|
try {
|
||||||
|
while (isTruncated) {
|
||||||
|
if (continuationToken != null) {
|
||||||
|
listObjectsV2Request.setContinuationToken(continuationToken);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 列举文件。
|
||||||
|
ListObjectsV2Result result = s3Client.listObjectsV2(listObjectsV2Request);
|
||||||
|
|
||||||
|
objectList.addAll(result.getObjectSummaries());
|
||||||
|
|
||||||
|
isTruncated = result.isTruncated();
|
||||||
|
continuationToken = result.getNextContinuationToken();
|
||||||
|
}
|
||||||
|
return objectList.stream().map(item -> {
|
||||||
|
StorageFileObject object = new StorageFileObject();
|
||||||
|
object.setPath(getRelativePath(item.getKey().substring(0, item.getKey().lastIndexOf("/"))));
|
||||||
|
object.setName(item.getKey().substring(item.getKey().lastIndexOf("/") + 1));
|
||||||
|
object.setSize(item.getSize());
|
||||||
|
object.setRawObject(item);
|
||||||
|
return object;
|
||||||
|
}).collect(Collectors.toList());
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new StorageException("列举文件失败:" + e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean deleteDir(String... path) {
|
||||||
|
List<StorageFileObject> objectList = listDir(buildPath(path));
|
||||||
|
AmazonS3 s3Client = getS3Client();
|
||||||
|
if (objectList.isEmpty()) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
int idx = 0;
|
||||||
|
int batchSize = 999;
|
||||||
|
while (objectList.size() > idx) {
|
||||||
|
if (objectList.size() - idx < batchSize) {
|
||||||
|
batchSize = objectList.size() - idx;
|
||||||
|
}
|
||||||
|
List<StorageFileObject> subList = objectList.subList(idx, idx + batchSize);
|
||||||
|
idx += batchSize;
|
||||||
|
DeleteObjectsRequest request = new DeleteObjectsRequest(config.getBucketName())
|
||||||
|
.withKeys(subList.stream().map(StorageFileObject::getFullPath).toArray(String[]::new));
|
||||||
|
try {
|
||||||
|
s3Client.deleteObjects(request);
|
||||||
|
} catch (Exception e) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private AmazonS3Client getS3Client() {
|
||||||
|
BasicAWSCredentials basicAwsCred = new BasicAWSCredentials(config.getAccessKeyId(), config.getAccessKeySecret());
|
||||||
|
ClientConfiguration clientConfiguration = new ClientConfiguration();
|
||||||
|
clientConfiguration.setProtocol(Protocol.HTTPS);
|
||||||
|
AmazonS3Client s3 = new AmazonS3Client(basicAwsCred,clientConfiguration);
|
||||||
|
S3ClientOptions options = S3ClientOptions.builder().setPathStyleAccess(true).setPayloadSigningEnabled(true).disableChunkedEncoding().build();
|
||||||
|
s3.setS3ClientOptions(options);
|
||||||
|
s3.setEndpoint(config.getEndpoint());
|
||||||
|
return s3;
|
||||||
|
}
|
||||||
|
|
||||||
|
private String buildPath(String... paths) {
|
||||||
|
if (StringUtils.isNotBlank(config.getPrefix())) {
|
||||||
|
return StorageUtil.joinPath(config.getPrefix(), paths);
|
||||||
|
} else {
|
||||||
|
return StorageUtil.joinPath(paths);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private String getRelativePath(String path) {
|
||||||
|
return StorageUtil.getRelativePath(path, config.getPrefix());
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,35 @@
|
|||||||
|
package com.ycwl.basic.storage.entity;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.EqualsAndHashCode;
|
||||||
|
|
||||||
|
@EqualsAndHashCode(callSuper = true)
|
||||||
|
@Data
|
||||||
|
public class AwsOssStorageConfig extends StorageConfig {
|
||||||
|
private String endpoint;
|
||||||
|
private String accessKeyId;
|
||||||
|
private String accessKeySecret;
|
||||||
|
private String bucketName;
|
||||||
|
private String url;
|
||||||
|
private String region;
|
||||||
|
private String prefix;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void checkEverythingOK() {
|
||||||
|
// TODO: 检查配置是否正确
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getUrl() {
|
||||||
|
String url = this.url;
|
||||||
|
if (url == null) {
|
||||||
|
url = bucketName + "." + endpoint;
|
||||||
|
}
|
||||||
|
if (!url.startsWith("http")) {
|
||||||
|
url = "https://" + url;
|
||||||
|
}
|
||||||
|
if (url.endsWith("/")) {
|
||||||
|
url = url.substring(0, url.length() - 1);
|
||||||
|
}
|
||||||
|
return url;
|
||||||
|
}
|
||||||
|
}
|
@ -4,6 +4,7 @@ import lombok.Getter;
|
|||||||
|
|
||||||
public enum StorageType {
|
public enum StorageType {
|
||||||
LOCAL("LOCAL"),
|
LOCAL("LOCAL"),
|
||||||
|
AWS_OSS("AWS_OSS"),
|
||||||
ALI_OSS("ALI_OSS");
|
ALI_OSS("ALI_OSS");
|
||||||
|
|
||||||
@Getter
|
@Getter
|
||||||
|
@ -157,6 +157,16 @@ storage:
|
|||||||
prefix: "user-video/"
|
prefix: "user-video/"
|
||||||
url: "https://oss.zhentuai.com"
|
url: "https://oss.zhentuai.com"
|
||||||
region: "cn-shanghai"
|
region: "cn-shanghai"
|
||||||
|
- name: "chaosheng"
|
||||||
|
type: "AWS_OSS"
|
||||||
|
config:
|
||||||
|
endpoint: "https://obs-cq.cucloud.cn"
|
||||||
|
accessKeyId: "5E628198FFEC47CEAFC211C341C60F767900"
|
||||||
|
accessKeySecret: "944346D1940E4AC6B5FCF981C7E589116498"
|
||||||
|
bucketName: "wsaiphoto"
|
||||||
|
prefix: "user-video/"
|
||||||
|
url: "https://wsaiphoto.obs-cq.cucloud.cn"
|
||||||
|
region: "obs-cq"
|
||||||
#阿里云人脸检测
|
#阿里云人脸检测
|
||||||
aliFace:
|
aliFace:
|
||||||
accessKeyId: "LTAI5tMwrmxVcUEKoH5QzLHx"
|
accessKeyId: "LTAI5tMwrmxVcUEKoH5QzLHx"
|
||||||
|
@ -157,6 +157,16 @@ storage:
|
|||||||
prefix: "user-video/"
|
prefix: "user-video/"
|
||||||
url: "https://oss.zhentuai.com"
|
url: "https://oss.zhentuai.com"
|
||||||
region: "cn-shanghai"
|
region: "cn-shanghai"
|
||||||
|
- name: "chaosheng"
|
||||||
|
type: "AWS_OSS"
|
||||||
|
config:
|
||||||
|
endpoint: "https://obs-cq.cucloud.cn"
|
||||||
|
accessKeyId: "5E628198FFEC47CEAFC211C341C60F767900"
|
||||||
|
accessKeySecret: "944346D1940E4AC6B5FCF981C7E589116498"
|
||||||
|
bucketName: "wsaiphoto"
|
||||||
|
prefix: "user-video/"
|
||||||
|
url: "https://wsaiphoto.obs-cq.cucloud.cn"
|
||||||
|
region: "obs-cq"
|
||||||
|
|
||||||
#阿里云人脸检测
|
#阿里云人脸检测
|
||||||
aliFace:
|
aliFace:
|
||||||
|
Loading…
x
Reference in New Issue
Block a user