From dea64e62e139643e09ff784c01d1398cff94ad8f Mon Sep 17 00:00:00 2001 From: Charles7c Date: Wed, 27 Dec 2023 23:55:47 +0800 Subject: [PATCH] =?UTF-8?q?refactor:=20=E6=96=B0=E5=A2=9E=20Amazon=20S3=20?= =?UTF-8?q?=E4=BE=9D=E8=B5=96=EF=BC=8C=E5=AE=8C=E5=96=84=E5=8A=A0=E8=BD=BD?= =?UTF-8?q?=E3=80=81=E5=8D=B8=E8=BD=BD=E5=AD=98=E5=82=A8=E5=BA=93=E9=85=8D?= =?UTF-8?q?=E7=BD=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- continew-admin-common/pom.xml | 5 ++ .../config/FileStorageConfigLoader.java | 56 +++++++++++++++ .../admin/system/enums/FileTypeEnum.java | 2 +- .../admin/system/enums/StorageTypeEnum.java | 46 +++++++++++++ .../admin/system/model/entity/StorageDO.java | 6 ++ .../admin/system/model/req/StorageReq.java | 8 +++ .../system/model/resp/StorageDetailResp.java | 7 ++ .../admin/system/model/resp/StorageResp.java | 7 ++ .../admin/system/service/FileService.java | 10 +++ .../admin/system/service/StorageService.java | 16 +++++ .../service/impl/StorageServiceImpl.java | 68 ++++++++++++------- .../changelog/v2.2.0/continew-admin_data.sql | 6 ++ .../changelog/v2.2.0/continew-admin_table.sql | 3 +- 13 files changed, 213 insertions(+), 27 deletions(-) create mode 100644 continew-admin-system/src/main/java/top/charles7c/continew/admin/system/config/FileStorageConfigLoader.java create mode 100644 continew-admin-system/src/main/java/top/charles7c/continew/admin/system/enums/StorageTypeEnum.java diff --git a/continew-admin-common/pom.xml b/continew-admin-common/pom.xml index 7ef23564..40bcbbbb 100644 --- a/continew-admin-common/pom.xml +++ b/continew-admin-common/pom.xml @@ -87,6 +87,11 @@ org.dromara.x-file-storage x-file-storage-spring + + + com.amazonaws + aws-java-sdk-s3 + diff --git a/continew-admin-system/src/main/java/top/charles7c/continew/admin/system/config/FileStorageConfigLoader.java b/continew-admin-system/src/main/java/top/charles7c/continew/admin/system/config/FileStorageConfigLoader.java new file mode 100644 index 00000000..22af9679 --- /dev/null +++ b/continew-admin-system/src/main/java/top/charles7c/continew/admin/system/config/FileStorageConfigLoader.java @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2022-present Charles7c Authors. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package top.charles7c.continew.admin.system.config; + +import java.util.List; + +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; + +import org.springframework.boot.ApplicationArguments; +import org.springframework.boot.ApplicationRunner; +import org.springframework.stereotype.Component; + +import cn.hutool.core.bean.BeanUtil; +import cn.hutool.core.collection.CollUtil; + +import top.charles7c.continew.admin.system.model.req.StorageReq; +import top.charles7c.continew.admin.system.model.resp.StorageResp; +import top.charles7c.continew.admin.system.service.StorageService; + +/** + * 文件存储配置加载器 + * + * @author Charles7c + * @since 2023/12/24 22:31 + */ +@Slf4j +@Component +@RequiredArgsConstructor +public class FileStorageConfigLoader implements ApplicationRunner { + + private final StorageService storageService; + + @Override + public void run(ApplicationArguments args) { + List storageList = storageService.list(null, null); + if (CollUtil.isEmpty(storageList)) { + return; + } + storageList.forEach(s -> storageService.load(BeanUtil.copyProperties(s, StorageReq.class))); + } +} diff --git a/continew-admin-system/src/main/java/top/charles7c/continew/admin/system/enums/FileTypeEnum.java b/continew-admin-system/src/main/java/top/charles7c/continew/admin/system/enums/FileTypeEnum.java index d6e88161..c1b4ba3f 100644 --- a/continew-admin-system/src/main/java/top/charles7c/continew/admin/system/enums/FileTypeEnum.java +++ b/continew-admin-system/src/main/java/top/charles7c/continew/admin/system/enums/FileTypeEnum.java @@ -28,7 +28,7 @@ import cn.hutool.core.util.StrUtil; import top.charles7c.continew.starter.data.mybatis.plus.base.IBaseEnum; /** - * 文件分类枚举 + * 文件类型枚举 * * @author Charles7c * @since 2023/12/23 13:38 diff --git a/continew-admin-system/src/main/java/top/charles7c/continew/admin/system/enums/StorageTypeEnum.java b/continew-admin-system/src/main/java/top/charles7c/continew/admin/system/enums/StorageTypeEnum.java new file mode 100644 index 00000000..9daf8206 --- /dev/null +++ b/continew-admin-system/src/main/java/top/charles7c/continew/admin/system/enums/StorageTypeEnum.java @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2022-present Charles7c Authors. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package top.charles7c.continew.admin.system.enums; + +import lombok.Getter; +import lombok.RequiredArgsConstructor; + +import top.charles7c.continew.starter.data.mybatis.plus.base.IBaseEnum; + +/** + * 存储类型枚举 + * + * @author Charles7c + * @since 2023/12/27 21:45 + */ +@Getter +@RequiredArgsConstructor +public enum StorageTypeEnum implements IBaseEnum { + + /** + * 兼容S3协议存储 + */ + S3(1, "兼容S3协议存储"), + + /** + * 本地存储 + */ + LOCAL(2, "本地存储"),; + + private final Integer value; + private final String description; +} diff --git a/continew-admin-system/src/main/java/top/charles7c/continew/admin/system/model/entity/StorageDO.java b/continew-admin-system/src/main/java/top/charles7c/continew/admin/system/model/entity/StorageDO.java index 0d95d239..bbe16eb8 100644 --- a/continew-admin-system/src/main/java/top/charles7c/continew/admin/system/model/entity/StorageDO.java +++ b/continew-admin-system/src/main/java/top/charles7c/continew/admin/system/model/entity/StorageDO.java @@ -22,6 +22,7 @@ import lombok.Data; import com.baomidou.mybatisplus.annotation.TableName; +import top.charles7c.continew.admin.system.enums.StorageTypeEnum; import top.charles7c.continew.starter.extension.crud.base.BaseDO; /** @@ -47,6 +48,11 @@ public class StorageDO extends BaseDO { */ private String code; + /** + * 类型 + */ + private StorageTypeEnum type; + /** * Access Key */ diff --git a/continew-admin-system/src/main/java/top/charles7c/continew/admin/system/model/req/StorageReq.java b/continew-admin-system/src/main/java/top/charles7c/continew/admin/system/model/req/StorageReq.java index 9b819787..644a4c6e 100644 --- a/continew-admin-system/src/main/java/top/charles7c/continew/admin/system/model/req/StorageReq.java +++ b/continew-admin-system/src/main/java/top/charles7c/continew/admin/system/model/req/StorageReq.java @@ -25,6 +25,7 @@ import lombok.Data; import io.swagger.v3.oas.annotations.media.Schema; import top.charles7c.continew.admin.common.enums.DisEnableStatusEnum; +import top.charles7c.continew.admin.system.enums.StorageTypeEnum; import top.charles7c.continew.starter.extension.crud.base.BaseReq; /** @@ -54,6 +55,13 @@ public class StorageReq extends BaseReq { @NotBlank(message = "编码不能为空") private String code; + /** + * 类型 + */ + @Schema(description = "类型") + @NotNull(message = "类型非法") + private StorageTypeEnum type; + /** * Access Key */ diff --git a/continew-admin-system/src/main/java/top/charles7c/continew/admin/system/model/resp/StorageDetailResp.java b/continew-admin-system/src/main/java/top/charles7c/continew/admin/system/model/resp/StorageDetailResp.java index e5b21d5d..143634a5 100644 --- a/continew-admin-system/src/main/java/top/charles7c/continew/admin/system/model/resp/StorageDetailResp.java +++ b/continew-admin-system/src/main/java/top/charles7c/continew/admin/system/model/resp/StorageDetailResp.java @@ -25,6 +25,7 @@ import io.swagger.v3.oas.annotations.media.Schema; import com.alibaba.excel.annotation.ExcelIgnoreUnannotated; import com.alibaba.excel.annotation.ExcelProperty; +import top.charles7c.continew.admin.system.enums.StorageTypeEnum; import top.charles7c.continew.starter.extension.crud.base.BaseDetailResp; /** @@ -55,6 +56,12 @@ public class StorageDetailResp extends BaseDetailResp { @ExcelProperty(value = "编码") private String code; + /** + * 类型 + */ + @Schema(description = "类型") + private StorageTypeEnum type; + /** * Access Key */ diff --git a/continew-admin-system/src/main/java/top/charles7c/continew/admin/system/model/resp/StorageResp.java b/continew-admin-system/src/main/java/top/charles7c/continew/admin/system/model/resp/StorageResp.java index 97cfc30b..50ee4120 100644 --- a/continew-admin-system/src/main/java/top/charles7c/continew/admin/system/model/resp/StorageResp.java +++ b/continew-admin-system/src/main/java/top/charles7c/continew/admin/system/model/resp/StorageResp.java @@ -22,6 +22,7 @@ import lombok.Data; import io.swagger.v3.oas.annotations.media.Schema; +import top.charles7c.continew.admin.system.enums.StorageTypeEnum; import top.charles7c.continew.starter.extension.crud.base.BaseResp; /** @@ -49,6 +50,12 @@ public class StorageResp extends BaseResp { @Schema(description = "编码") private String code; + /** + * 类型 + */ + @Schema(description = "类型") + private StorageTypeEnum type; + /** * Access Key */ diff --git a/continew-admin-system/src/main/java/top/charles7c/continew/admin/system/service/FileService.java b/continew-admin-system/src/main/java/top/charles7c/continew/admin/system/service/FileService.java index 3bbe45c9..d0daa2c3 100644 --- a/continew-admin-system/src/main/java/top/charles7c/continew/admin/system/service/FileService.java +++ b/continew-admin-system/src/main/java/top/charles7c/continew/admin/system/service/FileService.java @@ -34,6 +34,16 @@ import top.charles7c.continew.starter.extension.crud.base.BaseService; */ public interface FileService extends BaseService { + /** + * 上传 + * + * @param file + * 文件信息 + */ + default void upload(MultipartFile file) { + upload(file, null); + } + /** * 上传 * diff --git a/continew-admin-system/src/main/java/top/charles7c/continew/admin/system/service/StorageService.java b/continew-admin-system/src/main/java/top/charles7c/continew/admin/system/service/StorageService.java index ab0cdbf7..28bb81bb 100644 --- a/continew-admin-system/src/main/java/top/charles7c/continew/admin/system/service/StorageService.java +++ b/continew-admin-system/src/main/java/top/charles7c/continew/admin/system/service/StorageService.java @@ -46,4 +46,20 @@ public interface StorageService extends BaseService implements StorageService { + @Resource + private FileService fileService; private final ApplicationContext applicationContext; private final FileStorageService fileStorageService; - @Resource - private final FileService fileService; @Override public Long add(StorageReq req) { String code = req.getCode(); CheckUtils.throwIf(this.isCodeExists(code, null), "新增失败,[{}] 已存在", code); req.setStatus(DisEnableStatusEnum.ENABLE); - this.loadFileStorage(req); + this.load(req); return super.add(req); } @@ -87,7 +89,8 @@ public class StorageServiceImpl CheckUtils.throwIf( Boolean.TRUE.equals(oldStorage.getIsDefault()) && DisEnableStatusEnum.DISABLE.equals(req.getStatus()), "[{}] 是默认存储库,不允许禁用", oldStorage.getName()); - this.loadFileStorage(req); + this.unload(oldStorage.getCode()); + this.load(req); super.update(req, id); } @@ -95,7 +98,7 @@ public class StorageServiceImpl public void delete(List ids) { CheckUtils.throwIf(fileService.countByStorageIds(ids) > 0, "所选存储库存在文件关联,请删除文件后重试"); List storageList = baseMapper.lambdaQuery().in(StorageDO::getId, ids).list(); - storageList.forEach(s -> this.removeFileStorage(s.getCode())); + storageList.forEach(s -> this.unload(s.getCode())); super.delete(ids); } @@ -109,29 +112,44 @@ public class StorageServiceImpl return baseMapper.lambdaQuery().eq(StorageDO::getCode, code).one(); } - /** - * 加载存储配置 - * - * @param req - * 存储配置信息 - */ - private void loadFileStorage(StorageReq req) { + @Override + public void load(StorageReq req) { CopyOnWriteArrayList fileStorageList = fileStorageService.getFileStorageList(); - FileStorageProperties.LocalPlusConfig localPlusConfig = new FileStorageProperties.LocalPlusConfig(); - localPlusConfig.setPlatform(req.getCode()); - localPlusConfig.setStoragePath(req.getBucketName()); - localPlusConfig.setDomain(req.getDomain()); - fileStorageList - .addAll(FileStorageServiceBuilder.buildLocalPlusFileStorage(Collections.singletonList(localPlusConfig))); + String bucketName = req.getBucketName(); + StorageTypeEnum type = req.getType(); + switch (type) { + case LOCAL -> { + ValidationUtils.throwIfBlank(bucketName, "存储路径不能为空"); + FileStorageProperties.LocalPlusConfig config = new FileStorageProperties.LocalPlusConfig(); + config.setPlatform(req.getCode()); + config.setStoragePath(bucketName); + config.setDomain(req.getDomain()); + fileStorageList + .addAll(FileStorageServiceBuilder.buildLocalPlusFileStorage(Collections.singletonList(config))); + } + case S3 -> { + String accessKey = req.getAccessKey(); + String secretKey = req.getSecretKey(); + String endpoint = req.getEndpoint(); + ValidationUtils.throwIfBlank(accessKey, "Access Key不能为空"); + ValidationUtils.throwIfBlank(secretKey, "Secret Key不能为空"); + ValidationUtils.throwIfBlank(endpoint, "Endpoint不能为空"); + ValidationUtils.throwIfBlank(bucketName, "桶名称不能为空"); + FileStorageProperties.AmazonS3Config config = new FileStorageProperties.AmazonS3Config(); + config.setPlatform(req.getCode()); + config.setAccessKey(accessKey); + config.setSecretKey(secretKey); + config.setEndPoint(endpoint); + config.setBucketName(bucketName); + config.setDomain(req.getDomain()); + fileStorageList.addAll( + FileStorageServiceBuilder.buildAmazonS3FileStorage(Collections.singletonList(config), null)); + } + } } - /** - * 移除存储配置 - * - * @param code - * 存储配置编码 - */ - private void removeFileStorage(String code) { + @Override + public void unload(String code) { CopyOnWriteArrayList fileStorageList = fileStorageService.getFileStorageList(); FileStorage fileStorage = fileStorageService.getFileStorage(code); fileStorageList.remove(fileStorage); diff --git a/continew-admin-webapi/src/main/resources/db/changelog/v2.2.0/continew-admin_data.sql b/continew-admin-webapi/src/main/resources/db/changelog/v2.2.0/continew-admin_data.sql index e3c9c437..bf29ff69 100644 --- a/continew-admin-webapi/src/main/resources/db/changelog/v2.2.0/continew-admin_data.sql +++ b/continew-admin-webapi/src/main/resources/db/changelog/v2.2.0/continew-admin_data.sql @@ -15,3 +15,9 @@ VALUES (1102, '存储修改', 1100, 3, NULL, NULL, NULL, NULL, b'0', b'0', b'0', 'system:storage:update', 2, 1, 1, NOW(), NULL, NULL), (1103, '存储删除', 1100, 3, NULL, NULL, NULL, NULL, b'0', b'0', b'0', 'system:storage:delete', 3, 1, 1, NOW(), NULL, NULL), (1104, '存储导出', 1100, 3, NULL, NULL, NULL, NULL, b'0', b'0', b'0', 'system:storage:export', 4, 1, 1, NOW(), NULL, NULL); + +-- 初始化默认存储库 +INSERT IGNORE INTO `sys_storage` +(`id`, `name`, `code`, `type`, `access_key`, `secret_key`, `endpoint`, `bucket_name`, `domain`, `description`, `is_default`, `sort`, `status`, `create_user`, `create_time`, `update_user`, `update_time`) +VALUES +(1, '本地存储', 'local', 2, NULL, NULL, NULL, '/data/file/', '', '本地存储', b'1', 1, 1, 1, NOW(), NULL, NULL); \ No newline at end of file diff --git a/continew-admin-webapi/src/main/resources/db/changelog/v2.2.0/continew-admin_table.sql b/continew-admin-webapi/src/main/resources/db/changelog/v2.2.0/continew-admin_table.sql index efd4c0b7..2cde0dc1 100644 --- a/continew-admin-webapi/src/main/resources/db/changelog/v2.2.0/continew-admin_table.sql +++ b/continew-admin-webapi/src/main/resources/db/changelog/v2.2.0/continew-admin_table.sql @@ -24,11 +24,12 @@ CREATE TABLE IF NOT EXISTS `sys_storage` ( `id` bigint(20) AUTO_INCREMENT COMMENT 'ID', `name` varchar(100) NOT NULL COMMENT '名称', `code` varchar(30) NOT NULL COMMENT '编码', + `type` tinyint(1) UNSIGNED NOT NULL DEFAULT 1 COMMENT '类型(1:兼容S3协议存储;2:本地存储)', `access_key` varchar(255) DEFAULT NULL COMMENT 'Access Key(访问密钥)', `secret_key` varchar(255) DEFAULT NULL COMMENT 'Secret Key(私有访问密钥)', `endpoint` varchar(255) DEFAULT NULL COMMENT 'Endpoint(终端节点)', `bucket_name` varchar(255) DEFAULT NULL COMMENT '桶名称', - `domain` varchar(255) DEFAULT NULL COMMENT '自定义域名', + `domain` varchar(255) NOT NULL DEFAULT '' COMMENT '自定义域名', `description` varchar(200) DEFAULT NULL COMMENT '描述', `is_default` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否为默认存储', `sort` int NOT NULL DEFAULT 999 COMMENT '排序',