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 '排序',