From 8cadea285aaada6abed91fa046af23e99a02baee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=A7=8B=E8=BE=9E=E6=9C=AA=E5=AF=92?= <545073804@qq.com> Date: Tue, 24 Mar 2026 23:42:51 +0800 Subject: [PATCH] =?UTF-8?q?remove=20=E7=A7=BB=E9=99=A4=20=E6=97=A7?= =?UTF-8?q?=E7=9A=84S3=E5=AE=A2=E6=88=B7=E7=AB=AF=20update=20=E6=9B=B4?= =?UTF-8?q?=E6=96=B0=20=E6=96=87=E4=BB=B6=E4=B8=8A=E4=BC=A0=E4=BD=BF?= =?UTF-8?q?=E7=94=A8=E6=96=B0=E7=9A=84S3=E5=AE=A2=E6=88=B7=E7=AB=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../client/AbstractS3StorageClientImpl.java | 49 +- .../client/DefaultS3StorageClientImpl.java | 8 +- .../oss/{s3 => }/client/S3StorageClient.java | 12 +- .../common/oss/{s3 => }/config/Config.java | 2 +- .../config/S3AccessControlPolicyConfig.java | 4 +- .../config/S3AsyncExecutorConfig.java | 2 +- .../config/S3StorageClientConfig.java | 41 +- .../dromara/common/oss/core/OssClient.java | 568 ------------------ .../common/oss/core/WriteOutSubscriber.java | 21 - .../common/oss/entity/UploadResult.java | 16 - .../oss/{s3 => }/enums/AccessPolicy.java | 4 +- .../common/oss/enums/AccessPolicyType.java | 56 -- .../common/oss/exception/OssException.java | 24 - .../exception/S3StorageException.java | 2 +- .../common/oss/factory/OssFactory.java | 74 --- .../factory/S3StorageClientFactory.java | 10 +- .../io/OutputStreamDownloadSubscriber.java | 4 +- .../{s3/domain => model}/GetObjectResult.java | 2 +- .../domain => model}/HandleAsyncResult.java | 2 +- .../oss/{s3/domain => model}/Options.java | 2 +- .../{s3/domain => model}/PutObjectResult.java | 2 +- .../oss/{s3 => }/util/BucketUrlUtil.java | 2 +- .../oss/{s3 => }/util/S3ObjectUtil.java | 2 +- .../service/impl/SysOssConfigServiceImpl.java | 2 +- .../service/impl/SysOssServiceImpl.java | 56 +- 25 files changed, 121 insertions(+), 846 deletions(-) rename ruoyi-common/ruoyi-common-oss/src/main/java/org/dromara/common/oss/{s3 => }/client/AbstractS3StorageClientImpl.java (91%) rename ruoyi-common/ruoyi-common-oss/src/main/java/org/dromara/common/oss/{s3 => }/client/DefaultS3StorageClientImpl.java (94%) rename ruoyi-common/ruoyi-common-oss/src/main/java/org/dromara/common/oss/{s3 => }/client/S3StorageClient.java (97%) rename ruoyi-common/ruoyi-common-oss/src/main/java/org/dromara/common/oss/{s3 => }/config/Config.java (89%) rename ruoyi-common/ruoyi-common-oss/src/main/java/org/dromara/common/oss/{s3 => }/config/S3AccessControlPolicyConfig.java (93%) rename ruoyi-common/ruoyi-common-oss/src/main/java/org/dromara/common/oss/{s3 => }/config/S3AsyncExecutorConfig.java (97%) rename ruoyi-common/ruoyi-common-oss/src/main/java/org/dromara/common/oss/{s3 => }/config/S3StorageClientConfig.java (84%) delete mode 100644 ruoyi-common/ruoyi-common-oss/src/main/java/org/dromara/common/oss/core/OssClient.java delete mode 100644 ruoyi-common/ruoyi-common-oss/src/main/java/org/dromara/common/oss/core/WriteOutSubscriber.java delete mode 100644 ruoyi-common/ruoyi-common-oss/src/main/java/org/dromara/common/oss/entity/UploadResult.java rename ruoyi-common/ruoyi-common-oss/src/main/java/org/dromara/common/oss/{s3 => }/enums/AccessPolicy.java (92%) delete mode 100644 ruoyi-common/ruoyi-common-oss/src/main/java/org/dromara/common/oss/enums/AccessPolicyType.java delete mode 100644 ruoyi-common/ruoyi-common-oss/src/main/java/org/dromara/common/oss/exception/OssException.java rename ruoyi-common/ruoyi-common-oss/src/main/java/org/dromara/common/oss/{s3 => }/exception/S3StorageException.java (96%) delete mode 100644 ruoyi-common/ruoyi-common-oss/src/main/java/org/dromara/common/oss/factory/OssFactory.java rename ruoyi-common/ruoyi-common-oss/src/main/java/org/dromara/common/oss/{s3 => }/factory/S3StorageClientFactory.java (90%) rename ruoyi-common/ruoyi-common-oss/src/main/java/org/dromara/common/oss/{s3 => }/io/OutputStreamDownloadSubscriber.java (95%) rename ruoyi-common/ruoyi-common-oss/src/main/java/org/dromara/common/oss/{s3/domain => model}/GetObjectResult.java (96%) rename ruoyi-common/ruoyi-common-oss/src/main/java/org/dromara/common/oss/{s3/domain => model}/HandleAsyncResult.java (95%) rename ruoyi-common/ruoyi-common-oss/src/main/java/org/dromara/common/oss/{s3/domain => model}/Options.java (97%) rename ruoyi-common/ruoyi-common-oss/src/main/java/org/dromara/common/oss/{s3/domain => model}/PutObjectResult.java (90%) rename ruoyi-common/ruoyi-common-oss/src/main/java/org/dromara/common/oss/{s3 => }/util/BucketUrlUtil.java (98%) rename ruoyi-common/ruoyi-common-oss/src/main/java/org/dromara/common/oss/{s3 => }/util/S3ObjectUtil.java (97%) diff --git a/ruoyi-common/ruoyi-common-oss/src/main/java/org/dromara/common/oss/s3/client/AbstractS3StorageClientImpl.java b/ruoyi-common/ruoyi-common-oss/src/main/java/org/dromara/common/oss/client/AbstractS3StorageClientImpl.java similarity index 91% rename from ruoyi-common/ruoyi-common-oss/src/main/java/org/dromara/common/oss/s3/client/AbstractS3StorageClientImpl.java rename to ruoyi-common/ruoyi-common-oss/src/main/java/org/dromara/common/oss/client/AbstractS3StorageClientImpl.java index 4b214648d..b0c878485 100644 --- a/ruoyi-common/ruoyi-common-oss/src/main/java/org/dromara/common/oss/s3/client/AbstractS3StorageClientImpl.java +++ b/ruoyi-common/ruoyi-common-oss/src/main/java/org/dromara/common/oss/client/AbstractS3StorageClientImpl.java @@ -1,14 +1,15 @@ -package org.dromara.common.oss.s3.client; +package org.dromara.common.oss.client; import cn.hutool.core.lang.Assert; import cn.hutool.core.util.IdUtil; +import lombok.extern.slf4j.Slf4j; import org.dromara.common.core.utils.StringUtils; -import org.dromara.common.oss.s3.config.S3StorageClientConfig; -import org.dromara.common.oss.s3.domain.GetObjectResult; -import org.dromara.common.oss.s3.domain.HandleAsyncResult; -import org.dromara.common.oss.s3.domain.PutObjectResult; -import org.dromara.common.oss.s3.exception.S3StorageException; -import org.dromara.common.oss.s3.io.OutputStreamDownloadSubscriber; +import org.dromara.common.oss.config.S3StorageClientConfig; +import org.dromara.common.oss.model.GetObjectResult; +import org.dromara.common.oss.model.HandleAsyncResult; +import org.dromara.common.oss.model.PutObjectResult; +import org.dromara.common.oss.exception.S3StorageException; +import org.dromara.common.oss.io.OutputStreamDownloadSubscriber; import software.amazon.awssdk.core.async.AsyncRequestBody; import software.amazon.awssdk.core.async.AsyncResponseTransformer; import software.amazon.awssdk.core.async.ResponsePublisher; @@ -44,6 +45,7 @@ import java.util.function.Function; * * @author 秋辞未寒 */ +@Slf4j public abstract class AbstractS3StorageClientImpl implements S3StorageClient { private final AtomicBoolean initialized = new AtomicBoolean(false); @@ -182,12 +184,22 @@ public abstract class AbstractS3StorageClientImpl implements S3StorageClient { @Override public HandleAsyncResult doCustomUpload(AsyncRequestBody body, Consumer putObjectRequestBuilderConsumer, Collection transferListeners) { - return doCustomUpload(body, putObjectRequestBuilderConsumer, transferListeners, (completedUpload, throwable) -> HandleAsyncResult.of(completedUpload.response(), throwable)); + return doCustomUpload(body, putObjectRequestBuilderConsumer, transferListeners, (completedUpload, throwable) -> { + if (completedUpload == null) { + return HandleAsyncResult.of(null, throwable); + } + return HandleAsyncResult.of(completedUpload.response(), throwable); + }); } @Override public HandleAsyncResult doCustomUpload(AsyncRequestBody body, Consumer putObjectRequestBuilderConsumer) { - return doCustomUpload(body, putObjectRequestBuilderConsumer, null, (completedUpload, throwable) -> HandleAsyncResult.of(completedUpload.response(), throwable)); + return doCustomUpload(body, putObjectRequestBuilderConsumer, null, (completedUpload, throwable) -> { + if (completedUpload == null) { + return HandleAsyncResult.of(null, throwable); + } + return HandleAsyncResult.of(completedUpload.response(), throwable); + }); } @Override @@ -232,9 +244,7 @@ public abstract class AbstractS3StorageClientImpl implements S3StorageClient { @Override public PutObjectResult bucketUpload(String bucket, String key, InputStream in, long contentLength) { - AsyncRequestBody body = AsyncRequestBody.fromInputStream(builder -> builder.inputStream(in) - .contentLength(contentLength) - .executor(asyncExecutor)); + AsyncRequestBody body = AsyncRequestBody.fromInputStream(in,contentLength,asyncExecutor); return bucketUpload(bucket, key, body); } @@ -252,7 +262,13 @@ public abstract class AbstractS3StorageClientImpl implements S3StorageClient { private PutObjectResult bucketUpload(String bucket, String key, AsyncRequestBody body) { - HandleAsyncResult result = doCustomUpload(body, builder -> builder.bucket(bucket).key(key)); + Long contentLength = body.contentLength().orElse(null); + HandleAsyncResult result = doCustomUpload(body, builder -> { + builder.bucket(bucket) + .key(key) + .contentLength(contentLength) + ; + }); if (result.isFailure()) { throw S3StorageException.form(result.error()); } @@ -261,7 +277,12 @@ public abstract class AbstractS3StorageClientImpl implements S3StorageClient { throw S3StorageException.form("response is empty."); } PutObjectResponse response = opt.get(); - return PutObjectResult.form(null, key, response.eTag(), response.size()); + String bucketUrl = config.getBucketUrl(bucket); + // 不知道什么原因导致 response.size() 返回了一个 null size ,此处做一个适配... + Long size = response.size(); + size = size == null ? contentLength : size; + log.info("response size:{}", size); + return PutObjectResult.form("%s/%s".formatted(bucketUrl,key), key, response.eTag(), size == null?0:size); } @Override diff --git a/ruoyi-common/ruoyi-common-oss/src/main/java/org/dromara/common/oss/s3/client/DefaultS3StorageClientImpl.java b/ruoyi-common/ruoyi-common-oss/src/main/java/org/dromara/common/oss/client/DefaultS3StorageClientImpl.java similarity index 94% rename from ruoyi-common/ruoyi-common-oss/src/main/java/org/dromara/common/oss/s3/client/DefaultS3StorageClientImpl.java rename to ruoyi-common/ruoyi-common-oss/src/main/java/org/dromara/common/oss/client/DefaultS3StorageClientImpl.java index 2aed095d1..bac2b8c22 100644 --- a/ruoyi-common/ruoyi-common-oss/src/main/java/org/dromara/common/oss/s3/client/DefaultS3StorageClientImpl.java +++ b/ruoyi-common/ruoyi-common-oss/src/main/java/org/dromara/common/oss/client/DefaultS3StorageClientImpl.java @@ -1,8 +1,8 @@ -package org.dromara.common.oss.s3.client; +package org.dromara.common.oss.client; -import org.dromara.common.oss.s3.config.S3AsyncExecutorConfig; -import org.dromara.common.oss.s3.config.S3StorageClientConfig; -import org.dromara.common.oss.s3.exception.S3StorageException; +import org.dromara.common.oss.config.S3AsyncExecutorConfig; +import org.dromara.common.oss.config.S3StorageClientConfig; +import org.dromara.common.oss.exception.S3StorageException; import software.amazon.awssdk.auth.credentials.AwsBasicCredentials; import software.amazon.awssdk.auth.credentials.StaticCredentialsProvider; import software.amazon.awssdk.http.nio.netty.NettyNioAsyncHttpClient; diff --git a/ruoyi-common/ruoyi-common-oss/src/main/java/org/dromara/common/oss/s3/client/S3StorageClient.java b/ruoyi-common/ruoyi-common-oss/src/main/java/org/dromara/common/oss/client/S3StorageClient.java similarity index 97% rename from ruoyi-common/ruoyi-common-oss/src/main/java/org/dromara/common/oss/s3/client/S3StorageClient.java rename to ruoyi-common/ruoyi-common-oss/src/main/java/org/dromara/common/oss/client/S3StorageClient.java index 31128201e..b35c26558 100644 --- a/ruoyi-common/ruoyi-common-oss/src/main/java/org/dromara/common/oss/s3/client/S3StorageClient.java +++ b/ruoyi-common/ruoyi-common-oss/src/main/java/org/dromara/common/oss/client/S3StorageClient.java @@ -1,11 +1,11 @@ -package org.dromara.common.oss.s3.client; +package org.dromara.common.oss.client; import cn.hutool.core.util.IdUtil; -import org.dromara.common.oss.s3.config.S3StorageClientConfig; -import org.dromara.common.oss.s3.domain.GetObjectResult; -import org.dromara.common.oss.s3.domain.HandleAsyncResult; -import org.dromara.common.oss.s3.domain.PutObjectResult; -import org.dromara.common.oss.s3.io.OutputStreamDownloadSubscriber; +import org.dromara.common.oss.config.S3StorageClientConfig; +import org.dromara.common.oss.model.GetObjectResult; +import org.dromara.common.oss.model.HandleAsyncResult; +import org.dromara.common.oss.model.PutObjectResult; +import org.dromara.common.oss.io.OutputStreamDownloadSubscriber; import software.amazon.awssdk.core.async.AsyncRequestBody; import software.amazon.awssdk.core.async.AsyncResponseTransformer; import software.amazon.awssdk.services.s3.model.GetObjectRequest; diff --git a/ruoyi-common/ruoyi-common-oss/src/main/java/org/dromara/common/oss/s3/config/Config.java b/ruoyi-common/ruoyi-common-oss/src/main/java/org/dromara/common/oss/config/Config.java similarity index 89% rename from ruoyi-common/ruoyi-common-oss/src/main/java/org/dromara/common/oss/s3/config/Config.java rename to ruoyi-common/ruoyi-common-oss/src/main/java/org/dromara/common/oss/config/Config.java index ef8c0c2eb..6ef1d06f4 100644 --- a/ruoyi-common/ruoyi-common-oss/src/main/java/org/dromara/common/oss/s3/config/Config.java +++ b/ruoyi-common/ruoyi-common-oss/src/main/java/org/dromara/common/oss/config/Config.java @@ -1,4 +1,4 @@ -package org.dromara.common.oss.s3.config; +package org.dromara.common.oss.config; /** * 配置对象接口 diff --git a/ruoyi-common/ruoyi-common-oss/src/main/java/org/dromara/common/oss/s3/config/S3AccessControlPolicyConfig.java b/ruoyi-common/ruoyi-common-oss/src/main/java/org/dromara/common/oss/config/S3AccessControlPolicyConfig.java similarity index 93% rename from ruoyi-common/ruoyi-common-oss/src/main/java/org/dromara/common/oss/s3/config/S3AccessControlPolicyConfig.java rename to ruoyi-common/ruoyi-common-oss/src/main/java/org/dromara/common/oss/config/S3AccessControlPolicyConfig.java index 90a9430fc..ad6113c8d 100644 --- a/ruoyi-common/ruoyi-common-oss/src/main/java/org/dromara/common/oss/s3/config/S3AccessControlPolicyConfig.java +++ b/ruoyi-common/ruoyi-common-oss/src/main/java/org/dromara/common/oss/config/S3AccessControlPolicyConfig.java @@ -1,7 +1,7 @@ -package org.dromara.common.oss.s3.config; +package org.dromara.common.oss.config; import lombok.Builder; -import org.dromara.common.oss.s3.enums.AccessPolicy; +import org.dromara.common.oss.enums.AccessPolicy; import org.jspecify.annotations.NonNull; import java.io.Serial; diff --git a/ruoyi-common/ruoyi-common-oss/src/main/java/org/dromara/common/oss/s3/config/S3AsyncExecutorConfig.java b/ruoyi-common/ruoyi-common-oss/src/main/java/org/dromara/common/oss/config/S3AsyncExecutorConfig.java similarity index 97% rename from ruoyi-common/ruoyi-common-oss/src/main/java/org/dromara/common/oss/s3/config/S3AsyncExecutorConfig.java rename to ruoyi-common/ruoyi-common-oss/src/main/java/org/dromara/common/oss/config/S3AsyncExecutorConfig.java index b828de42c..2c7b86008 100644 --- a/ruoyi-common/ruoyi-common-oss/src/main/java/org/dromara/common/oss/s3/config/S3AsyncExecutorConfig.java +++ b/ruoyi-common/ruoyi-common-oss/src/main/java/org/dromara/common/oss/config/S3AsyncExecutorConfig.java @@ -1,4 +1,4 @@ -package org.dromara.common.oss.s3.config; +package org.dromara.common.oss.config; import lombok.Builder; diff --git a/ruoyi-common/ruoyi-common-oss/src/main/java/org/dromara/common/oss/s3/config/S3StorageClientConfig.java b/ruoyi-common/ruoyi-common-oss/src/main/java/org/dromara/common/oss/config/S3StorageClientConfig.java similarity index 84% rename from ruoyi-common/ruoyi-common-oss/src/main/java/org/dromara/common/oss/s3/config/S3StorageClientConfig.java rename to ruoyi-common/ruoyi-common-oss/src/main/java/org/dromara/common/oss/config/S3StorageClientConfig.java index d0ecdfac6..76abfe5c5 100644 --- a/ruoyi-common/ruoyi-common-oss/src/main/java/org/dromara/common/oss/s3/config/S3StorageClientConfig.java +++ b/ruoyi-common/ruoyi-common-oss/src/main/java/org/dromara/common/oss/config/S3StorageClientConfig.java @@ -1,4 +1,4 @@ -package org.dromara.common.oss.s3.config; +package org.dromara.common.oss.config; import cn.hutool.http.HttpUtil; import lombok.Builder; @@ -7,9 +7,10 @@ import lombok.RequiredArgsConstructor; import org.dromara.common.core.constant.SystemConstants; import org.dromara.common.core.utils.StringUtils; import org.dromara.common.oss.constant.OssConstant; +import org.dromara.common.oss.enums.AccessPolicy; +import org.dromara.common.oss.exception.S3StorageException; import org.dromara.common.oss.properties.OssProperties; -import org.dromara.common.oss.s3.exception.S3StorageException; -import org.dromara.common.oss.s3.util.BucketUrlUtil; +import org.dromara.common.oss.util.BucketUrlUtil; import org.jspecify.annotations.NonNull; import software.amazon.awssdk.regions.Region; @@ -200,6 +201,15 @@ public class S3StorageClientConfig implements Config !s.isBlank()) .orElseThrow(() -> S3StorageException.form("bucket is not configured.")); + return getBucketUrl(bucket); + } + + /** + * 获取桶URL地址 + * + * @return 桶URL地址 + */ + public String getBucketUrl(String bucket) { // 如果已经配置了自定义域名,则优先使用域名 String url = domain() // 检查携带协议头 @@ -256,16 +266,17 @@ public class S3StorageClientConfig implements Config { - x.source(filePath).putObjectRequest( - y -> y.bucket(properties.getBucketName()) - .key(key) - .contentMD5(StringUtils.isNotEmpty(md5Digest) ? md5Digest : null) - .contentType(contentType) - // 用于设置对象的访问控制列表(ACL)。不同云厂商对ACL的支持和实现方式有所不同, - // 因此根据具体的云服务提供商,你可能需要进行不同的配置(自行开启,阿里云有acl权限配置,腾讯云没有acl权限配置) - //.acl(getAccessPolicy().getObjectCannedACL()) - .build() - ); - if (log.isDebugEnabled()) { - x.addTransferListener(LoggingTransferListener.create()); - } - } - ); - // 等待上传完成并获取上传结果 - CompletedFileUpload uploadResult = fileUpload.completionFuture().join(); - String eTag = uploadResult.response().eTag(); - - // 提取上传结果中的 ETag,并构建一个自定义的 UploadResult 对象 - return new UploadResult(getUrl() + StringUtils.SLASH + key, key, eTag); - } catch (Exception e) { - // 捕获异常并抛出自定义异常 - throw new OssException("上传文件失败,请检查配置信息:[" + e.getMessage() + "]"); - } finally { - // 无论上传是否成功,最终都会删除临时文件 - FileUtils.del(filePath); - } - } - - /** - * 上传 InputStream 到 Amazon S3 - * - * @param inputStream 要上传的输入流 - * @param key 在 Amazon S3 中的对象键 - * @param length 输入流的长度 - * @param contentType 文件内容类型 - * @return UploadResult 包含上传后的文件信息 - * @throws OssException 如果上传失败,抛出自定义异常 - */ - public UploadResult upload(InputStream inputStream, String key, Long length, String contentType) { - // 如果输入流不是 ByteArrayInputStream,则将其读取为字节数组再创建 ByteArrayInputStream - if (!(inputStream instanceof ByteArrayInputStream)) { - inputStream = new ByteArrayInputStream(IoUtil.readBytes(inputStream)); - } - try { - // 创建异步请求体(length如果为空会报错) - BlockingInputStreamAsyncRequestBody body = BlockingInputStreamAsyncRequestBody.builder() - .contentLength(length) - .subscribeTimeout(Duration.ofSeconds(120)) - .build(); - - // 使用 transferManager 进行上传 - Upload upload = transferManager.upload( - x -> { - x.requestBody(body).putObjectRequest( - y -> y.bucket(properties.getBucketName()) - .key(key) - .contentType(contentType) - // 用于设置对象的访问控制列表(ACL)。不同云厂商对ACL的支持和实现方式有所不同, - // 因此根据具体的云服务提供商,你可能需要进行不同的配置(自行开启,阿里云有acl权限配置,腾讯云没有acl权限配置) - //.acl(getAccessPolicy().getObjectCannedACL()) - .build() - ); - if (log.isDebugEnabled()) { - x.addTransferListener(LoggingTransferListener.create()); - } - } - ); - - // 将输入流写入请求体 - body.writeInputStream(inputStream); - - // 等待文件上传操作完成 - CompletedUpload uploadResult = upload.completionFuture().join(); - String eTag = uploadResult.response().eTag(); - - // 提取上传结果中的 ETag,并构建一个自定义的 UploadResult 对象 - return new UploadResult(getUrl() + StringUtils.SLASH + key, key, eTag); - } catch (Exception e) { - throw new OssException("上传文件失败,请检查配置信息:[" + e.getMessage() + "]"); - } - } - - /** - * 下载文件从 Amazon S3 到临时目录 - * - * @param path 文件在 Amazon S3 中的对象键 - * @return 下载后的文件在本地的临时路径 - * @throws OssException 如果下载失败,抛出自定义异常 - */ - public Path fileDownload(String path) { - // 构建临时文件 - Path tempFilePath = FileUtils.createTempFile().toPath(); - // 使用 S3TransferManager 下载文件 - FileDownload downloadFile = transferManager.downloadFile( - x -> { - x.destination(tempFilePath).getObjectRequest( - y -> y.bucket(properties.getBucketName()) - .key(removeBaseUrl(path)) - .build() - ); - if (log.isDebugEnabled()) { - x.addTransferListener(LoggingTransferListener.create()); - } - } - ); - // 等待文件下载操作完成 - downloadFile.completionFuture().join(); - return tempFilePath; - } - - /** - * 下载文件从 Amazon S3 到 输出流 - * - * @param key 文件在 Amazon S3 中的对象键 - * @param out 输出流 - * @param consumer 自定义处理逻辑 - * @throws OssException 如果下载失败,抛出自定义异常 - */ - public void download(String key, OutputStream out, Consumer consumer) { - try { - this.download(key, consumer).writeTo(out); - } catch (Exception e) { - throw new OssException("文件下载失败,错误信息:[" + e.getMessage() + "]"); - } - } - - /** - * 下载文件从 Amazon S3 到 输出流 - * - * @param key 文件在 Amazon S3 中的对象键 - * @param contentLengthConsumer 文件大小消费者函数 - * @return 写出订阅器 - * @throws OssException 如果下载失败,抛出自定义异常 - */ - public WriteOutSubscriber download(String key, Consumer contentLengthConsumer) { - try { - DownloadRequest.TypedBuilder> typedBuilder = DownloadRequest.builder() - // 使用发布订阅转换器 - .responseTransformer(AsyncResponseTransformer.toPublisher()) - // 文件对象 - .getObjectRequest(y -> y.bucket(properties.getBucketName()).key(key).build()); - if (log.isDebugEnabled()) { - typedBuilder.addTransferListener(LoggingTransferListener.create()); - } - - // 使用 S3TransferManager 下载文件 - Download> publisherDownload = transferManager.download(typedBuilder.build()); - // 获取下载发布订阅转换器 - ResponsePublisher publisher = publisherDownload.completionFuture().join().result(); - // 执行文件大小消费者函数 - Optional.ofNullable(contentLengthConsumer) - .ifPresent(lengthConsumer -> lengthConsumer.accept(publisher.response().contentLength())); - - // 构建写出订阅器对象 - return out -> { - // 创建可写入的字节通道 - try (WritableByteChannel channel = Channels.newChannel(out)) { - // 订阅数据 - publisher.subscribe(byteBuffer -> { - while (byteBuffer.hasRemaining()) { - try { - channel.write(byteBuffer); - } catch (IOException e) { - throw new RuntimeException(e); - } - } - }).join(); - } - }; - } catch (Exception e) { - throw new OssException("文件下载失败,错误信息:[" + e.getMessage() + "]"); - } - } - - /** - * 删除云存储服务中指定路径下文件 - * - * @param path 指定路径 - */ - public void delete(String path) { - try { - client.deleteObject( - x -> x.bucket(properties.getBucketName()) - .key(removeBaseUrl(path)) - .build()); - } catch (Exception e) { - throw new OssException("删除文件失败,请检查配置信息:[" + e.getMessage() + "]"); - } - } - - /** - * 创建下载请求的预签名URL - * - * @param objectKey 对象KEY - * @param expiredTime 链接授权到期时间 - */ - public String createPresignedGetUrl(String objectKey, Duration expiredTime) { - // 使用 AWS S3 预签名 URL 的生成器 获取下载对象的预签名 URL - URL url = presigner.presignGetObject( - x -> x.signatureDuration(expiredTime) - .getObjectRequest( - y -> y.bucket(properties.getBucketName()) - .key(objectKey) - .build()) - .build()) - .url(); - return url.toExternalForm(); - } - - /** - * 创建上传请求的预签名URL - * - * @param objectKey 对象KEY - * @param expiredTime 链接授权到期时间 - * @param metadata 元数据 - */ - public String createPresignedPutUrl(String objectKey, Duration expiredTime, Map metadata) { - // 使用 AWS S3 预签名 URL 的生成器 获取上传文件对象的预签名 URL - URL url = presigner.presignPutObject( - x -> x.signatureDuration(expiredTime) - .putObjectRequest( - y -> y.bucket(properties.getBucketName()) - .key(objectKey) - .metadata(metadata) - .build()) - .build()) - .url(); - return url.toExternalForm(); - } - - /** - * 上传 byte[] 数据到 Amazon S3,使用指定的后缀构造对象键。 - * - * @param data 要上传的 byte[] 数据 - * @param suffix 对象键的后缀 - * @return UploadResult 包含上传后的文件信息 - * @throws OssException 如果上传失败,抛出自定义异常 - */ - public UploadResult uploadSuffix(byte[] data, String suffix, String contentType) { - return upload(new ByteArrayInputStream(data), getPath(properties.getPrefix(), suffix), Long.valueOf(data.length), contentType); - } - - /** - * 上传 InputStream 到 Amazon S3,使用指定的后缀构造对象键。 - * - * @param inputStream 要上传的输入流 - * @param suffix 对象键的后缀 - * @param length 输入流的长度 - * @return UploadResult 包含上传后的文件信息 - * @throws OssException 如果上传失败,抛出自定义异常 - */ - public UploadResult uploadSuffix(InputStream inputStream, String suffix, Long length, String contentType) { - return upload(inputStream, getPath(properties.getPrefix(), suffix), length, contentType); - } - - /** - * 上传文件到 Amazon S3,使用指定的后缀构造对象键 - * - * @param file 要上传的文件 - * @param suffix 对象键的后缀 - * @return UploadResult 包含上传后的文件信息 - * @throws OssException 如果上传失败,抛出自定义异常 - */ - public UploadResult uploadSuffix(File file, String suffix) { - return upload(file.toPath(), getPath(properties.getPrefix(), suffix), null, FileUtils.getMimeType(suffix)); - } - - /** - * 获取文件输入流 - * - * @param path 完整文件路径 - * @return 输入流 - */ - public InputStream getObjectContent(String path) throws IOException { - // 下载文件到临时目录 - Path tempFilePath = fileDownload(path); - // 创建输入流 - InputStream inputStream = Files.newInputStream(tempFilePath); - // 删除临时文件 - FileUtils.del(tempFilePath); - // 返回对象内容的输入流 - return inputStream; - } - - /** - * 获取 S3 客户端的终端点 URL - * - * @return 终端点 URL - */ - public String getEndpoint() { - // 根据配置文件中的是否使用 HTTPS,设置协议头部 - String header = getIsHttps(); - // 拼接协议头部和终端点,得到完整的终端点 URL - return header + properties.getEndpoint(); - } - - /** - * 获取 S3 客户端的终端点 URL(自定义域名) - * - * @return 终端点 URL - */ - public String getDomain() { - // 从配置中获取域名、终端点、是否使用 HTTPS 等信息 - String domain = properties.getDomainUrl(); - String endpoint = properties.getEndpoint(); - String header = getIsHttps(); - - // 如果是云服务商,直接返回域名或终端点 - if (StringUtils.containsAny(endpoint, OssConstant.CLOUD_SERVICE)) { - return StringUtils.isNotEmpty(domain) ? header + domain : header + endpoint; - } - - // 如果是 MinIO,处理域名并返回 - if (StringUtils.isNotEmpty(domain)) { - return domain.startsWith(Constants.HTTPS) || domain.startsWith(Constants.HTTP) ? domain : header + domain; - } - - // 返回终端点 - return header + endpoint; - } - - /** - * 根据传入的 region 参数返回相应的 AWS 区域 - * 如果 region 参数非空,使用 Region.of 方法创建并返回对应的 AWS 区域对象 - * 如果 region 参数为空,返回一个默认的 AWS 区域(例如,us-east-1),作为广泛支持的区域 - * - * @return 对应的 AWS 区域对象,或者默认的广泛支持的区域(us-east-1) - */ - public Region of() { - //AWS 区域字符串 - String region = properties.getRegion(); - // 如果 region 参数非空,使用 Region.of 方法创建对应的 AWS 区域对象,否则返回默认区域 - return StringUtils.isNotEmpty(region) ? Region.of(region) : Region.US_EAST_1; - } - - /** - * 获取云存储服务的URL - * - * @return 文件路径 - */ - public String getUrl() { - String domain = properties.getDomainUrl(); - String endpoint = properties.getEndpoint(); - String header = getIsHttps(); - // 云服务商直接返回 - if (StringUtils.containsAny(endpoint, OssConstant.CLOUD_SERVICE)) { - return header + (StringUtils.isNotEmpty(domain) ? domain : properties.getBucketName() + "." + endpoint); - } - // MinIO 单独处理 - if (StringUtils.isNotEmpty(domain)) { - // 如果 domain 以 "https://" 或 "http://" 开头 - return (domain.startsWith(Constants.HTTPS) || domain.startsWith(Constants.HTTP)) ? - domain + StringUtils.SLASH + properties.getBucketName() : header + domain + StringUtils.SLASH + properties.getBucketName(); - } - return header + endpoint + StringUtils.SLASH + properties.getBucketName(); - } - - /** - * 生成一个符合特定规则的、唯一的文件路径。通过使用日期、UUID、前缀和后缀等元素的组合,确保了文件路径的独一无二性 - * - * @param prefix 前缀 - * @param suffix 后缀 - * @return 文件路径 - */ - public String getPath(String prefix, String suffix) { - // 生成uuid - String uuid = IdUtil.fastSimpleUUID(); - // 生成日期路径 - String datePath = DateUtils.datePath(); - // 拼接路径 - String path = StringUtils.isNotEmpty(prefix) ? - prefix + StringUtils.SLASH + datePath + StringUtils.SLASH + uuid : datePath + StringUtils.SLASH + uuid; - return path + suffix; - } - - /** - * 移除路径中的基础URL部分,得到相对路径 - * - * @param path 完整的路径,包括基础URL和相对路径 - * @return 去除基础URL后的相对路径 - */ - public String removeBaseUrl(String path) { - return path.replace(getUrl() + StringUtils.SLASH, ""); - } - - /** - * 服务商 - */ - public String getConfigKey() { - return configKey; - } - - /** - * 获取是否使用 HTTPS 的配置,并返回相应的协议头部。 - * - * @return 协议头部,根据是否使用 HTTPS 返回 "https://" 或 "http://" - */ - public String getIsHttps() { - return SystemConstants.YES.equals(properties.getIsHttps()) ? Constants.HTTPS : Constants.HTTP; - } - - /** - * 检查配置是否相同 - * - * @param properties OSS 配置 - * @return 是否与当前客户端配置一致 - */ - public boolean checkPropertiesSame(OssProperties properties) { - return this.properties.equals(properties); - } - - /** - * 获取当前桶权限类型 - * - * @return 当前桶权限类型code - */ - public AccessPolicyType getAccessPolicy() { - return AccessPolicyType.getByType(properties.getAccessPolicy()); - } - -} diff --git a/ruoyi-common/ruoyi-common-oss/src/main/java/org/dromara/common/oss/core/WriteOutSubscriber.java b/ruoyi-common/ruoyi-common-oss/src/main/java/org/dromara/common/oss/core/WriteOutSubscriber.java deleted file mode 100644 index 3b1fa9ba0..000000000 --- a/ruoyi-common/ruoyi-common-oss/src/main/java/org/dromara/common/oss/core/WriteOutSubscriber.java +++ /dev/null @@ -1,21 +0,0 @@ -package org.dromara.common.oss.core; - -import java.io.IOException; - -/** - * 写出订阅器 - * - * @author 秋辞未寒 - */ -@FunctionalInterface -public interface WriteOutSubscriber { - - /** - * 将订阅到的数据写出到目标对象。 - * - * @param out 写出目标 - * @throws IOException 写出异常 - */ - void writeTo(T out) throws IOException; - -} diff --git a/ruoyi-common/ruoyi-common-oss/src/main/java/org/dromara/common/oss/entity/UploadResult.java b/ruoyi-common/ruoyi-common-oss/src/main/java/org/dromara/common/oss/entity/UploadResult.java deleted file mode 100644 index 26af1ff70..000000000 --- a/ruoyi-common/ruoyi-common-oss/src/main/java/org/dromara/common/oss/entity/UploadResult.java +++ /dev/null @@ -1,16 +0,0 @@ -package org.dromara.common.oss.entity; - -/** - * 上传返回体 - * - * @param url 文件访问地址 - * @param filename 文件名 - * @param eTag 存储服务返回的 ETag - * @author Lion Li - */ -public record UploadResult( - String url, - String filename, - String eTag -) { -} diff --git a/ruoyi-common/ruoyi-common-oss/src/main/java/org/dromara/common/oss/s3/enums/AccessPolicy.java b/ruoyi-common/ruoyi-common-oss/src/main/java/org/dromara/common/oss/enums/AccessPolicy.java similarity index 92% rename from ruoyi-common/ruoyi-common-oss/src/main/java/org/dromara/common/oss/s3/enums/AccessPolicy.java rename to ruoyi-common/ruoyi-common-oss/src/main/java/org/dromara/common/oss/enums/AccessPolicy.java index 8b722c724..0d5f4eeef 100644 --- a/ruoyi-common/ruoyi-common-oss/src/main/java/org/dromara/common/oss/s3/enums/AccessPolicy.java +++ b/ruoyi-common/ruoyi-common-oss/src/main/java/org/dromara/common/oss/enums/AccessPolicy.java @@ -1,8 +1,8 @@ -package org.dromara.common.oss.s3.enums; +package org.dromara.common.oss.enums; import lombok.AllArgsConstructor; import lombok.Getter; -import org.dromara.common.oss.s3.exception.S3StorageException; +import org.dromara.common.oss.exception.S3StorageException; import software.amazon.awssdk.services.s3.model.BucketCannedACL; import software.amazon.awssdk.services.s3.model.ObjectCannedACL; diff --git a/ruoyi-common/ruoyi-common-oss/src/main/java/org/dromara/common/oss/enums/AccessPolicyType.java b/ruoyi-common/ruoyi-common-oss/src/main/java/org/dromara/common/oss/enums/AccessPolicyType.java deleted file mode 100644 index 45b13beda..000000000 --- a/ruoyi-common/ruoyi-common-oss/src/main/java/org/dromara/common/oss/enums/AccessPolicyType.java +++ /dev/null @@ -1,56 +0,0 @@ -package org.dromara.common.oss.enums; - -import lombok.AllArgsConstructor; -import lombok.Getter; -import software.amazon.awssdk.services.s3.model.BucketCannedACL; -import software.amazon.awssdk.services.s3.model.ObjectCannedACL; - -/** - * 桶访问策略配置 - * - * @author 陈賝 - */ -@Getter -@AllArgsConstructor -public enum AccessPolicyType { - - /** - * private - */ - PRIVATE("0", BucketCannedACL.PRIVATE, ObjectCannedACL.PRIVATE), - - /** - * public - */ - PUBLIC("1", BucketCannedACL.PUBLIC_READ_WRITE, ObjectCannedACL.PUBLIC_READ_WRITE), - - /** - * custom - */ - CUSTOM("2", BucketCannedACL.PUBLIC_READ, ObjectCannedACL.PUBLIC_READ); - - /** - * 桶 权限类型(数据库值) - */ - private final String type; - - /** - * 桶 权限类型 - */ - private final BucketCannedACL bucketCannedACL; - - /** - * 文件对象 权限类型 - */ - private final ObjectCannedACL objectCannedACL; - - public static AccessPolicyType getByType(String type) { - for (AccessPolicyType value : values()) { - if (value.getType().equals(type)) { - return value; - } - } - throw new RuntimeException("'type' not found By " + type); - } - -} diff --git a/ruoyi-common/ruoyi-common-oss/src/main/java/org/dromara/common/oss/exception/OssException.java b/ruoyi-common/ruoyi-common-oss/src/main/java/org/dromara/common/oss/exception/OssException.java deleted file mode 100644 index b8bfe7032..000000000 --- a/ruoyi-common/ruoyi-common-oss/src/main/java/org/dromara/common/oss/exception/OssException.java +++ /dev/null @@ -1,24 +0,0 @@ -package org.dromara.common.oss.exception; - -import java.io.Serial; - -/** - * OSS异常类 - * - * @author Lion Li - */ -public class OssException extends RuntimeException { - - @Serial - private static final long serialVersionUID = 1L; - - /** - * 创建 OSS 业务异常。 - * - * @param msg 异常消息 - */ - public OssException(String msg) { - super(msg); - } - -} diff --git a/ruoyi-common/ruoyi-common-oss/src/main/java/org/dromara/common/oss/s3/exception/S3StorageException.java b/ruoyi-common/ruoyi-common-oss/src/main/java/org/dromara/common/oss/exception/S3StorageException.java similarity index 96% rename from ruoyi-common/ruoyi-common-oss/src/main/java/org/dromara/common/oss/s3/exception/S3StorageException.java rename to ruoyi-common/ruoyi-common-oss/src/main/java/org/dromara/common/oss/exception/S3StorageException.java index e9df33d85..77c3124b2 100644 --- a/ruoyi-common/ruoyi-common-oss/src/main/java/org/dromara/common/oss/s3/exception/S3StorageException.java +++ b/ruoyi-common/ruoyi-common-oss/src/main/java/org/dromara/common/oss/exception/S3StorageException.java @@ -1,4 +1,4 @@ -package org.dromara.common.oss.s3.exception; +package org.dromara.common.oss.exception; import java.io.Serial; diff --git a/ruoyi-common/ruoyi-common-oss/src/main/java/org/dromara/common/oss/factory/OssFactory.java b/ruoyi-common/ruoyi-common-oss/src/main/java/org/dromara/common/oss/factory/OssFactory.java deleted file mode 100644 index e3acfc519..000000000 --- a/ruoyi-common/ruoyi-common-oss/src/main/java/org/dromara/common/oss/factory/OssFactory.java +++ /dev/null @@ -1,74 +0,0 @@ -package org.dromara.common.oss.factory; - -import lombok.extern.slf4j.Slf4j; -import org.dromara.common.core.constant.CacheNames; -import org.dromara.common.core.utils.StringUtils; -import org.dromara.common.json.utils.JsonUtils; -import org.dromara.common.oss.constant.OssConstant; -import org.dromara.common.oss.core.OssClient; -import org.dromara.common.oss.exception.OssException; -import org.dromara.common.oss.properties.OssProperties; -import org.dromara.common.redis.utils.CacheUtils; -import org.dromara.common.redis.utils.RedisUtils; - -import java.util.Map; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.locks.ReentrantLock; - -/** - * 文件上传Factory - * - * @author Lion Li - */ -@Slf4j -public class OssFactory { - - private static final Map CLIENT_CACHE = new ConcurrentHashMap<>(); - private static final ReentrantLock LOCK = new ReentrantLock(); - - /** - * 获取默认 OSS 客户端实例。 - * - * @return 默认 OSS 客户端 - */ - public static OssClient instance() { - // 获取redis 默认类型 - String configKey = RedisUtils.getCacheObject(OssConstant.DEFAULT_CONFIG_KEY); - if (StringUtils.isEmpty(configKey)) { - throw new OssException("文件存储服务类型无法找到!"); - } - return instance(configKey); - } - - /** - * 根据配置键获取 OSS 客户端实例。 - * - * @param configKey 配置键 - * @return OSS 客户端 - */ - public static OssClient instance(String configKey) { - String json = CacheUtils.get(CacheNames.SYS_OSS_CONFIG, configKey); - if (json == null) { - throw new OssException("系统异常, '" + configKey + "'配置信息不存在!"); - } - OssProperties properties = JsonUtils.parseObject(json, OssProperties.class); - // 使用租户标识避免多个租户相同key实例覆盖 - OssClient client = CLIENT_CACHE.get(configKey); - // 客户端不存在或配置不相同则重新构建 - if (client == null || !client.checkPropertiesSame(properties)) { - LOCK.lock(); - try { - client = CLIENT_CACHE.get(configKey); - if (client == null || !client.checkPropertiesSame(properties)) { - CLIENT_CACHE.put(configKey, new OssClient(configKey, properties)); - log.info("创建OSS实例 key => {}", configKey); - return CLIENT_CACHE.get(configKey); - } - } finally { - LOCK.unlock(); - } - } - return client; - } - -} diff --git a/ruoyi-common/ruoyi-common-oss/src/main/java/org/dromara/common/oss/s3/factory/S3StorageClientFactory.java b/ruoyi-common/ruoyi-common-oss/src/main/java/org/dromara/common/oss/factory/S3StorageClientFactory.java similarity index 90% rename from ruoyi-common/ruoyi-common-oss/src/main/java/org/dromara/common/oss/s3/factory/S3StorageClientFactory.java rename to ruoyi-common/ruoyi-common-oss/src/main/java/org/dromara/common/oss/factory/S3StorageClientFactory.java index 83fe7cdfa..da56daaea 100644 --- a/ruoyi-common/ruoyi-common-oss/src/main/java/org/dromara/common/oss/s3/factory/S3StorageClientFactory.java +++ b/ruoyi-common/ruoyi-common-oss/src/main/java/org/dromara/common/oss/factory/S3StorageClientFactory.java @@ -1,4 +1,4 @@ -package org.dromara.common.oss.s3.factory; +package org.dromara.common.oss.factory; import lombok.extern.slf4j.Slf4j; import org.dromara.common.core.constant.CacheNames; @@ -6,10 +6,10 @@ import org.dromara.common.core.utils.StringUtils; import org.dromara.common.json.utils.JsonUtils; import org.dromara.common.oss.constant.OssConstant; import org.dromara.common.oss.properties.OssProperties; -import org.dromara.common.oss.s3.client.DefaultS3StorageClientImpl; -import org.dromara.common.oss.s3.client.S3StorageClient; -import org.dromara.common.oss.s3.config.S3StorageClientConfig; -import org.dromara.common.oss.s3.exception.S3StorageException; +import org.dromara.common.oss.client.DefaultS3StorageClientImpl; +import org.dromara.common.oss.client.S3StorageClient; +import org.dromara.common.oss.config.S3StorageClientConfig; +import org.dromara.common.oss.exception.S3StorageException; import org.dromara.common.redis.utils.CacheUtils; import org.dromara.common.redis.utils.RedisUtils; diff --git a/ruoyi-common/ruoyi-common-oss/src/main/java/org/dromara/common/oss/s3/io/OutputStreamDownloadSubscriber.java b/ruoyi-common/ruoyi-common-oss/src/main/java/org/dromara/common/oss/io/OutputStreamDownloadSubscriber.java similarity index 95% rename from ruoyi-common/ruoyi-common-oss/src/main/java/org/dromara/common/oss/s3/io/OutputStreamDownloadSubscriber.java rename to ruoyi-common/ruoyi-common-oss/src/main/java/org/dromara/common/oss/io/OutputStreamDownloadSubscriber.java index 062bd0b6b..229098141 100644 --- a/ruoyi-common/ruoyi-common-oss/src/main/java/org/dromara/common/oss/s3/io/OutputStreamDownloadSubscriber.java +++ b/ruoyi-common/ruoyi-common-oss/src/main/java/org/dromara/common/oss/io/OutputStreamDownloadSubscriber.java @@ -1,6 +1,6 @@ -package org.dromara.common.oss.s3.io; +package org.dromara.common.oss.io; -import org.dromara.common.oss.s3.exception.S3StorageException; +import org.dromara.common.oss.exception.S3StorageException; import java.io.FileOutputStream; import java.io.IOException; diff --git a/ruoyi-common/ruoyi-common-oss/src/main/java/org/dromara/common/oss/s3/domain/GetObjectResult.java b/ruoyi-common/ruoyi-common-oss/src/main/java/org/dromara/common/oss/model/GetObjectResult.java similarity index 96% rename from ruoyi-common/ruoyi-common-oss/src/main/java/org/dromara/common/oss/s3/domain/GetObjectResult.java rename to ruoyi-common/ruoyi-common-oss/src/main/java/org/dromara/common/oss/model/GetObjectResult.java index 2558c68ec..a486b1274 100644 --- a/ruoyi-common/ruoyi-common-oss/src/main/java/org/dromara/common/oss/s3/domain/GetObjectResult.java +++ b/ruoyi-common/ruoyi-common-oss/src/main/java/org/dromara/common/oss/model/GetObjectResult.java @@ -1,4 +1,4 @@ -package org.dromara.common.oss.s3.domain; +package org.dromara.common.oss.model; import java.time.LocalDateTime; import java.util.Map; diff --git a/ruoyi-common/ruoyi-common-oss/src/main/java/org/dromara/common/oss/s3/domain/HandleAsyncResult.java b/ruoyi-common/ruoyi-common-oss/src/main/java/org/dromara/common/oss/model/HandleAsyncResult.java similarity index 95% rename from ruoyi-common/ruoyi-common-oss/src/main/java/org/dromara/common/oss/s3/domain/HandleAsyncResult.java rename to ruoyi-common/ruoyi-common-oss/src/main/java/org/dromara/common/oss/model/HandleAsyncResult.java index a03232127..d98f08901 100644 --- a/ruoyi-common/ruoyi-common-oss/src/main/java/org/dromara/common/oss/s3/domain/HandleAsyncResult.java +++ b/ruoyi-common/ruoyi-common-oss/src/main/java/org/dromara/common/oss/model/HandleAsyncResult.java @@ -1,4 +1,4 @@ -package org.dromara.common.oss.s3.domain; +package org.dromara.common.oss.model; import java.util.Optional; diff --git a/ruoyi-common/ruoyi-common-oss/src/main/java/org/dromara/common/oss/s3/domain/Options.java b/ruoyi-common/ruoyi-common-oss/src/main/java/org/dromara/common/oss/model/Options.java similarity index 97% rename from ruoyi-common/ruoyi-common-oss/src/main/java/org/dromara/common/oss/s3/domain/Options.java rename to ruoyi-common/ruoyi-common-oss/src/main/java/org/dromara/common/oss/model/Options.java index 265eae9a3..cb30a5a21 100644 --- a/ruoyi-common/ruoyi-common-oss/src/main/java/org/dromara/common/oss/s3/domain/Options.java +++ b/ruoyi-common/ruoyi-common-oss/src/main/java/org/dromara/common/oss/model/Options.java @@ -1,4 +1,4 @@ -package org.dromara.common.oss.s3.domain; +package org.dromara.common.oss.model; import lombok.AccessLevel; import lombok.Data; diff --git a/ruoyi-common/ruoyi-common-oss/src/main/java/org/dromara/common/oss/s3/domain/PutObjectResult.java b/ruoyi-common/ruoyi-common-oss/src/main/java/org/dromara/common/oss/model/PutObjectResult.java similarity index 90% rename from ruoyi-common/ruoyi-common-oss/src/main/java/org/dromara/common/oss/s3/domain/PutObjectResult.java rename to ruoyi-common/ruoyi-common-oss/src/main/java/org/dromara/common/oss/model/PutObjectResult.java index a6f49285e..76e72aaa9 100644 --- a/ruoyi-common/ruoyi-common-oss/src/main/java/org/dromara/common/oss/s3/domain/PutObjectResult.java +++ b/ruoyi-common/ruoyi-common-oss/src/main/java/org/dromara/common/oss/model/PutObjectResult.java @@ -1,4 +1,4 @@ -package org.dromara.common.oss.s3.domain; +package org.dromara.common.oss.model; /** * Put文件对象结果 diff --git a/ruoyi-common/ruoyi-common-oss/src/main/java/org/dromara/common/oss/s3/util/BucketUrlUtil.java b/ruoyi-common/ruoyi-common-oss/src/main/java/org/dromara/common/oss/util/BucketUrlUtil.java similarity index 98% rename from ruoyi-common/ruoyi-common-oss/src/main/java/org/dromara/common/oss/s3/util/BucketUrlUtil.java rename to ruoyi-common/ruoyi-common-oss/src/main/java/org/dromara/common/oss/util/BucketUrlUtil.java index c07a5b941..a7e7fd91e 100644 --- a/ruoyi-common/ruoyi-common-oss/src/main/java/org/dromara/common/oss/s3/util/BucketUrlUtil.java +++ b/ruoyi-common/ruoyi-common-oss/src/main/java/org/dromara/common/oss/util/BucketUrlUtil.java @@ -1,4 +1,4 @@ -package org.dromara.common.oss.s3.util; +package org.dromara.common.oss.util; import lombok.AccessLevel; import lombok.NoArgsConstructor; diff --git a/ruoyi-common/ruoyi-common-oss/src/main/java/org/dromara/common/oss/s3/util/S3ObjectUtil.java b/ruoyi-common/ruoyi-common-oss/src/main/java/org/dromara/common/oss/util/S3ObjectUtil.java similarity index 97% rename from ruoyi-common/ruoyi-common-oss/src/main/java/org/dromara/common/oss/s3/util/S3ObjectUtil.java rename to ruoyi-common/ruoyi-common-oss/src/main/java/org/dromara/common/oss/util/S3ObjectUtil.java index 08f92bb06..9138949fa 100644 --- a/ruoyi-common/ruoyi-common-oss/src/main/java/org/dromara/common/oss/s3/util/S3ObjectUtil.java +++ b/ruoyi-common/ruoyi-common-oss/src/main/java/org/dromara/common/oss/util/S3ObjectUtil.java @@ -1,4 +1,4 @@ -package org.dromara.common.oss.s3.util; +package org.dromara.common.oss.util; import cn.hutool.core.util.IdUtil; import lombok.AccessLevel; diff --git a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysOssConfigServiceImpl.java b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysOssConfigServiceImpl.java index 02b46fdce..f3e2392ea 100644 --- a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysOssConfigServiceImpl.java +++ b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysOssConfigServiceImpl.java @@ -54,7 +54,7 @@ public class SysOssConfigServiceImpl implements ISysOssConfigService { // 加载OSS初始化配置 for (SysOssConfig config : list) { String configKey = config.getConfigKey(); - if ("0".equals(config.getStatus())) { + if (SystemConstants.YES.equals(config.getStatus())) { RedisUtils.setCacheObject(OssConstant.DEFAULT_CONFIG_KEY, configKey); } CacheUtils.put(CacheNames.SYS_OSS_CONFIG, config.getConfigKey(), JsonUtils.toJsonString(config)); diff --git a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysOssServiceImpl.java b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysOssServiceImpl.java index 3a02b3c41..f5b26150a 100644 --- a/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysOssServiceImpl.java +++ b/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysOssServiceImpl.java @@ -20,10 +20,12 @@ import org.dromara.common.core.utils.StringUtils; import org.dromara.common.core.utils.file.FileUtils; import org.dromara.common.json.utils.JsonUtils; import org.dromara.common.mybatis.core.page.PageQuery; -import org.dromara.common.oss.core.OssClient; -import org.dromara.common.oss.entity.UploadResult; -import org.dromara.common.oss.enums.AccessPolicyType; -import org.dromara.common.oss.factory.OssFactory; +import org.dromara.common.oss.client.S3StorageClient; +import org.dromara.common.oss.model.GetObjectResult; +import org.dromara.common.oss.model.PutObjectResult; +import org.dromara.common.oss.enums.AccessPolicy; +import org.dromara.common.oss.factory.S3StorageClientFactory; +import org.dromara.common.oss.util.S3ObjectUtil; import org.dromara.system.domain.SysOss; import org.dromara.system.domain.SysOssExt; import org.dromara.system.domain.bo.SysOssBo; @@ -191,8 +193,9 @@ public class SysOssServiceImpl implements ISysOssService, OssService { } FileUtils.setAttachmentResponseHeader(response, sysOss.getOriginalName()); response.setContentType(MediaType.APPLICATION_OCTET_STREAM_VALUE + "; charset=UTF-8"); - OssClient storage = OssFactory.instance(sysOss.getService()); - storage.download(sysOss.getFileName(), response.getOutputStream(), response::setContentLengthLong); + S3StorageClient instance = S3StorageClientFactory.instance(sysOss.getService()); + GetObjectResult result = instance.download(sysOss.getFileName(), response.getOutputStream()); + response.setContentLengthLong(result.size()); } /** @@ -209,18 +212,18 @@ public class SysOssServiceImpl implements ISysOssService, OssService { } String originalfileName = file.getOriginalFilename(); String suffix = StringUtils.substring(originalfileName, originalfileName.lastIndexOf("."), originalfileName.length()); - OssClient storage = OssFactory.instance(); - UploadResult uploadResult; + S3StorageClient instance = S3StorageClientFactory.instance(); try { - uploadResult = storage.uploadSuffix(file.getBytes(), suffix, file.getContentType()); + String pathKey = S3ObjectUtil.buildPathKey(originalfileName); + PutObjectResult result = instance.upload(pathKey, file.getInputStream(), file.getSize()); + SysOssExt ext1 = new SysOssExt(); + ext1.setFileSize(file.getSize()); + ext1.setContentType(file.getContentType()); + // 保存文件信息 + return buildResultEntity(originalfileName, suffix, instance.clientId(), result, ext1); } catch (IOException e) { throw new ServiceException(e.getMessage()); } - SysOssExt ext1 = new SysOssExt(); - ext1.setFileSize(file.getSize()); - ext1.setContentType(file.getContentType()); - // 保存文件信息 - return buildResultEntity(originalfileName, suffix, storage.getConfigKey(), uploadResult, ext1); } /** @@ -236,13 +239,13 @@ public class SysOssServiceImpl implements ISysOssService, OssService { } String originalfileName = file.getName(); String suffix = StringUtils.substring(originalfileName, originalfileName.lastIndexOf("."), originalfileName.length()); - OssClient storage = OssFactory.instance(); - long length = file.length(); - UploadResult uploadResult = storage.uploadSuffix(file, suffix); + S3StorageClient instance = S3StorageClientFactory.instance(); + String pathKey = S3ObjectUtil.buildPathKey(originalfileName); + PutObjectResult result = instance.upload(pathKey, file); SysOssExt ext1 = new SysOssExt(); - ext1.setFileSize(length); + ext1.setFileSize(result.size()); // 保存文件信息 - return buildResultEntity(originalfileName, suffix, storage.getConfigKey(), uploadResult, ext1); + return buildResultEntity(originalfileName, suffix, instance.clientId(), result, ext1); } /** @@ -256,11 +259,11 @@ public class SysOssServiceImpl implements ISysOssService, OssService { * @return 持久化后的文件信息视图 */ @NotNull - private SysOssVo buildResultEntity(String originalfileName, String suffix, String configKey, UploadResult uploadResult, SysOssExt ext1) { + private SysOssVo buildResultEntity(String originalfileName, String suffix, String configKey, PutObjectResult result, SysOssExt ext1) { SysOss oss = new SysOss(); - oss.setUrl(uploadResult.url()); + oss.setUrl(result.url()); oss.setFileSuffix(suffix); - oss.setFileName(uploadResult.filename()); + oss.setFileName(result.key()); oss.setOriginalName(originalfileName); oss.setService(configKey); oss.setExt1(JsonUtils.toJsonString(ext1)); @@ -283,8 +286,7 @@ public class SysOssServiceImpl implements ISysOssService, OssService { } List list = baseMapper.selectByIds(ids); for (SysOss sysOss : list) { - OssClient storage = OssFactory.instance(sysOss.getService()); - storage.delete(sysOss.getUrl()); + S3StorageClientFactory.instance(sysOss.getService()).delete(sysOss.getFileName()); } return baseMapper.deleteByIds(ids) > 0; } @@ -296,10 +298,10 @@ public class SysOssServiceImpl implements ISysOssService, OssService { * @return oss 匹配Url的OSS对象 */ private SysOssVo matchingUrl(SysOssVo oss) { - OssClient storage = OssFactory.instance(oss.getService()); + S3StorageClient instance = S3StorageClientFactory.instance(oss.getService()); // 仅修改桶类型为 private 的URL,临时URL时长为120s - if (AccessPolicyType.PRIVATE == storage.getAccessPolicy()) { - oss.setUrl(storage.createPresignedGetUrl(oss.getFileName(), Duration.ofSeconds(120))); + if (instance.verifyConfig(config -> AccessPolicy.PRIVATE.equals(config.accessControlPolicyConfig().accessPolicy()))) { + oss.setUrl(instance.presignGetUrl(oss.getFileName(), Duration.ofSeconds(120))); } return oss; }