From 5a2c5be088b8e1ae063b11952c2b810cb6075284 Mon Sep 17 00:00:00 2001 From: Charles7c Date: Tue, 26 Dec 2023 22:58:29 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E6=96=B0=E5=A2=9E=E9=83=A8=E5=88=86?= =?UTF-8?q?=E5=AD=98=E5=82=A8=E5=BA=93=E7=AE=A1=E7=90=86=E5=90=8E=E7=AB=AF?= =?UTF-8?q?=20API?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- continew-admin-common/pom.xml | 6 + .../mybatis/MyBatisPlusMetaObjectHandler.java | 6 +- .../admin/system/config/FileRecorderImpl.java | 82 ++++++++ .../admin/system/enums/FileTypeEnum.java | 16 ++ .../admin/system/mapper/StorageMapper.java | 28 +++ .../admin/system/model/entity/FileDO.java | 12 +- .../admin/system/model/entity/StorageDO.java | 94 +++++++++ .../system/model/query/StorageQuery.java | 55 ++++++ .../admin/system/model/req/StorageReq.java | 111 +++++++++++ .../system/model/resp/StorageDetailResp.java | 120 ++++++++++++ .../admin/system/model/resp/StorageResp.java | 105 ++++++++++ .../admin/system/service/FileService.java | 26 ++- .../admin/system/service/StorageService.java | 49 +++++ .../system/service/impl/FileServiceImpl.java | 54 ++++- .../service/impl/StorageServiceImpl.java | 185 ++++++++++++++++++ .../admin/ContiNewAdminApplication.java | 2 + .../webapi/system/StorageController.java | 41 ++++ .../changelog/v2.2.0/continew-admin_table.sql | 4 +- 18 files changed, 981 insertions(+), 15 deletions(-) create mode 100644 continew-admin-system/src/main/java/top/charles7c/continew/admin/system/config/FileRecorderImpl.java create mode 100644 continew-admin-system/src/main/java/top/charles7c/continew/admin/system/mapper/StorageMapper.java create mode 100644 continew-admin-system/src/main/java/top/charles7c/continew/admin/system/model/entity/StorageDO.java create mode 100644 continew-admin-system/src/main/java/top/charles7c/continew/admin/system/model/query/StorageQuery.java create mode 100644 continew-admin-system/src/main/java/top/charles7c/continew/admin/system/model/req/StorageReq.java create mode 100644 continew-admin-system/src/main/java/top/charles7c/continew/admin/system/model/resp/StorageDetailResp.java create mode 100644 continew-admin-system/src/main/java/top/charles7c/continew/admin/system/model/resp/StorageResp.java create mode 100644 continew-admin-system/src/main/java/top/charles7c/continew/admin/system/service/StorageService.java create mode 100644 continew-admin-system/src/main/java/top/charles7c/continew/admin/system/service/impl/StorageServiceImpl.java create mode 100644 continew-admin-webapi/src/main/java/top/charles7c/continew/admin/webapi/system/StorageController.java diff --git a/continew-admin-common/pom.xml b/continew-admin-common/pom.xml index e59e3dc9..7ef23564 100644 --- a/continew-admin-common/pom.xml +++ b/continew-admin-common/pom.xml @@ -82,6 +82,12 @@ sms4j-spring-boot-starter + + + org.dromara.x-file-storage + x-file-storage-spring + + org.freemarker diff --git a/continew-admin-common/src/main/java/top/charles7c/continew/admin/common/config/mybatis/MyBatisPlusMetaObjectHandler.java b/continew-admin-common/src/main/java/top/charles7c/continew/admin/common/config/mybatis/MyBatisPlusMetaObjectHandler.java index 1f81caa3..255bc574 100644 --- a/continew-admin-common/src/main/java/top/charles7c/continew/admin/common/config/mybatis/MyBatisPlusMetaObjectHandler.java +++ b/continew-admin-common/src/main/java/top/charles7c/continew/admin/common/config/mybatis/MyBatisPlusMetaObjectHandler.java @@ -61,11 +61,11 @@ public class MyBatisPlusMetaObjectHandler implements MetaObjectHandler { Long createUser = LoginHelper.getUserId(); LocalDateTime createTime = LocalDateTime.now(); if (metaObject.getOriginalObject() instanceof BaseDO baseDO) { - // 继承了 BaseDO 的类,填充创建信息 + // 继承了 BaseDO 的类,填充创建信息字段 baseDO.setCreateUser(ObjectUtil.defaultIfNull(baseDO.getCreateUser(), createUser)); baseDO.setCreateTime(ObjectUtil.defaultIfNull(baseDO.getCreateTime(), createTime)); } else { - // 未继承 BaseDO 的类,如存在创建信息则进行填充 + // 未继承 BaseDO 的类,如存在创建信息字段则进行填充 this.fillFieldValue(metaObject, CREATE_USER, createUser, false); this.fillFieldValue(metaObject, CREATE_TIME, createTime, false); } @@ -94,7 +94,7 @@ public class MyBatisPlusMetaObjectHandler implements MetaObjectHandler { baseDO.setUpdateUser(updateUser); baseDO.setUpdateTime(updateTime); } else { - // 未继承 BaseDO 的类,根据类中拥有的修改信息进行填充,不存在修改信息不进行填充 + // 未继承 BaseDO 的类,根据类中拥有的修改信息字段进行填充,不存在修改信息字段不进行填充 this.fillFieldValue(metaObject, UPDATE_USER, updateUser, true); this.fillFieldValue(metaObject, UPDATE_TIME, updateTime, true); } diff --git a/continew-admin-system/src/main/java/top/charles7c/continew/admin/system/config/FileRecorderImpl.java b/continew-admin-system/src/main/java/top/charles7c/continew/admin/system/config/FileRecorderImpl.java new file mode 100644 index 00000000..fddcbca1 --- /dev/null +++ b/continew-admin-system/src/main/java/top/charles7c/continew/admin/system/config/FileRecorderImpl.java @@ -0,0 +1,82 @@ +/* + * 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 lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; + +import org.dromara.x.file.storage.core.FileInfo; +import org.dromara.x.file.storage.core.recorder.FileRecorder; +import org.springframework.stereotype.Component; + +import cn.hutool.core.date.DateUtil; +import cn.hutool.core.util.EscapeUtil; + +import top.charles7c.continew.admin.common.util.helper.LoginHelper; +import top.charles7c.continew.admin.system.enums.FileTypeEnum; +import top.charles7c.continew.admin.system.mapper.FileMapper; +import top.charles7c.continew.admin.system.mapper.StorageMapper; +import top.charles7c.continew.admin.system.model.entity.FileDO; +import top.charles7c.continew.admin.system.model.entity.StorageDO; + +/** + * 文件记录实现类 + * + * @author Charles7c + * @since 2023/12/24 22:31 + */ +@Slf4j +@Component +@RequiredArgsConstructor +public class FileRecorderImpl implements FileRecorder { + + private final FileMapper fileMapper; + private final StorageMapper storageMapper; + + @Override + public boolean save(FileInfo fileInfo) { + FileDO file = new FileDO(); + file.setName(EscapeUtil.unescape(fileInfo.getOriginalFilename())); + file.setSize(fileInfo.getSize()); + file.setUrl(fileInfo.getUrl()); + file.setExtension(fileInfo.getExt()); + file.setType(FileTypeEnum.getByExtension(file.getExtension())); + StorageDO storage = storageMapper.lambdaQuery().eq(StorageDO::getCode, fileInfo.getPlatform()).one(); + file.setStorageId(storage.getId()); + file.setCreateTime(DateUtil.toLocalDateTime(fileInfo.getCreateTime())); + file.setUpdateUser(LoginHelper.getUserId()); + file.setUpdateTime(file.getCreateTime()); + fileMapper.insert(file); + return true; + } + + @Override + public FileInfo getByUrl(String url) { + FileDO file = fileMapper.lambdaQuery().eq(FileDO::getUrl, url).one(); + FileInfo fileInfo = new FileInfo(); + fileInfo.setOriginalFilename(file.getName()); + fileInfo.setSize(file.getSize()); + fileInfo.setUrl(file.getUrl()); + fileInfo.setExt(file.getExtension()); + return fileInfo; + } + + @Override + public boolean delete(String url) { + return fileMapper.lambdaUpdate().eq(FileDO::getUrl, url).remove(); + } +} \ No newline at end of file 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 384e4475..d6e88161 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 @@ -16,12 +16,15 @@ package top.charles7c.continew.admin.system.enums; +import java.util.Arrays; import java.util.Collections; import java.util.List; import lombok.Getter; import lombok.RequiredArgsConstructor; +import cn.hutool.core.util.StrUtil; + import top.charles7c.continew.starter.data.mybatis.plus.base.IBaseEnum; /** @@ -62,4 +65,17 @@ public enum FileTypeEnum implements IBaseEnum { private final Integer value; private final String description; private final List extensions; + + /** + * 根据扩展名查询 + * + * @param extension + * 扩展名 + * @return 文件类型 + */ + public static FileTypeEnum getByExtension(String extension) { + return Arrays.stream(FileTypeEnum.values()) + .filter(t -> t.getExtensions().contains(StrUtil.emptyIfNull(extension).toLowerCase())).findFirst() + .orElse(FileTypeEnum.UNKNOWN); + } } diff --git a/continew-admin-system/src/main/java/top/charles7c/continew/admin/system/mapper/StorageMapper.java b/continew-admin-system/src/main/java/top/charles7c/continew/admin/system/mapper/StorageMapper.java new file mode 100644 index 00000000..cee45005 --- /dev/null +++ b/continew-admin-system/src/main/java/top/charles7c/continew/admin/system/mapper/StorageMapper.java @@ -0,0 +1,28 @@ +/* + * 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.mapper; + +import top.charles7c.continew.admin.system.model.entity.StorageDO; +import top.charles7c.continew.starter.data.mybatis.plus.base.BaseMapper; + +/** + * 存储库 Mapper + * + * @author Charles7c + * @since 2023/12/26 22:09 + */ +public interface StorageMapper extends BaseMapper {} \ No newline at end of file diff --git a/continew-admin-system/src/main/java/top/charles7c/continew/admin/system/model/entity/FileDO.java b/continew-admin-system/src/main/java/top/charles7c/continew/admin/system/model/entity/FileDO.java index f3d497ce..dadc1250 100644 --- a/continew-admin-system/src/main/java/top/charles7c/continew/admin/system/model/entity/FileDO.java +++ b/continew-admin-system/src/main/java/top/charles7c/continew/admin/system/model/entity/FileDO.java @@ -20,7 +20,7 @@ import java.io.Serial; import lombok.Data; -import com.baomidou.mybatisplus.annotation.TableName; +import com.baomidou.mybatisplus.annotation.*; import top.charles7c.continew.admin.system.enums.FileTypeEnum; import top.charles7c.continew.starter.extension.crud.base.BaseDO; @@ -38,6 +38,9 @@ public class FileDO extends BaseDO { @Serial private static final long serialVersionUID = 1L; + @TableId(type = IdType.ASSIGN_ID) + private Long id; + /** * 名称 */ @@ -58,18 +61,13 @@ public class FileDO extends BaseDO { */ private String extension; - /** - * MIME类型 - */ - private String mimeType; - /** * 类型 */ private FileTypeEnum type; /** - * 存储库ID + * 存储库 ID */ private Long storageId; } \ No newline at end of file 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 new file mode 100644 index 00000000..0d95d239 --- /dev/null +++ b/continew-admin-system/src/main/java/top/charles7c/continew/admin/system/model/entity/StorageDO.java @@ -0,0 +1,94 @@ +/* + * 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.model.entity; + +import java.io.Serial; + +import lombok.Data; + +import com.baomidou.mybatisplus.annotation.TableName; + +import top.charles7c.continew.starter.extension.crud.base.BaseDO; + +/** + * 存储库实体 + * + * @author Charles7c + * @since 2023/12/26 22:09 + */ +@Data +@TableName("sys_storage") +public class StorageDO extends BaseDO { + + @Serial + private static final long serialVersionUID = 1L; + + /** + * 名称 + */ + private String name; + + /** + * 编码 + */ + private String code; + + /** + * Access Key + */ + private String accessKey; + + /** + * Secret Key + */ + private String secretKey; + + /** + * Endpoint + */ + private String endpoint; + + /** + * 桶名称 + */ + private String bucketName; + + /** + * 自定义域名 + */ + private String domain; + + /** + * 描述 + */ + private String description; + + /** + * 是否为默认存储 + */ + private Boolean isDefault; + + /** + * 排序 + */ + private Integer sort; + + /** + * 状态 + */ + private Integer status; +} \ No newline at end of file diff --git a/continew-admin-system/src/main/java/top/charles7c/continew/admin/system/model/query/StorageQuery.java b/continew-admin-system/src/main/java/top/charles7c/continew/admin/system/model/query/StorageQuery.java new file mode 100644 index 00000000..71fb8865 --- /dev/null +++ b/continew-admin-system/src/main/java/top/charles7c/continew/admin/system/model/query/StorageQuery.java @@ -0,0 +1,55 @@ +/* + * 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.model.query; + +import java.io.Serial; +import java.io.Serializable; + +import lombok.Data; + +import io.swagger.v3.oas.annotations.media.Schema; + +import top.charles7c.continew.starter.data.mybatis.plus.query.Query; +import top.charles7c.continew.starter.data.mybatis.plus.query.QueryType; + +/** + * 存储库查询条件 + * + * @author Charles7c + * @since 2023/12/26 22:09 + */ +@Data +@Schema(description = "存储库查询条件") +public class StorageQuery implements Serializable { + + @Serial + private static final long serialVersionUID = 1L; + + /** + * 名称 + */ + @Schema(description = "名称") + @Query(type = QueryType.INNER_LIKE) + private String name; + + /** + * 状态 + */ + @Schema(description = "状态") + @Query(type = QueryType.EQUAL) + private Integer status; +} \ No newline at end of file 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 new file mode 100644 index 00000000..9b819787 --- /dev/null +++ b/continew-admin-system/src/main/java/top/charles7c/continew/admin/system/model/req/StorageReq.java @@ -0,0 +1,111 @@ +/* + * 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.model.req; + +import java.io.Serial; + +import jakarta.validation.constraints.*; + +import lombok.Data; + +import io.swagger.v3.oas.annotations.media.Schema; + +import top.charles7c.continew.admin.common.enums.DisEnableStatusEnum; +import top.charles7c.continew.starter.extension.crud.base.BaseReq; + +/** + * 创建或修改存储库信息 + * + * @author Charles7c + * @since 2023/12/26 22:09 + */ +@Data +@Schema(description = "创建或修改存储库信息") +public class StorageReq extends BaseReq { + + @Serial + private static final long serialVersionUID = 1L; + + /** + * 名称 + */ + @Schema(description = "名称") + @NotBlank(message = "名称不能为空") + private String name; + + /** + * 编码 + */ + @Schema(description = "编码") + @NotBlank(message = "编码不能为空") + private String code; + + /** + * Access Key + */ + @Schema(description = "Access Key") + private String accessKey; + + /** + * Secret Key + */ + @Schema(description = "Secret Key") + private String secretKey; + + /** + * Endpoint + */ + @Schema(description = "Endpoint") + private String endpoint; + + /** + * 桶名称 + */ + @Schema(description = "桶名称") + private String bucketName; + + /** + * 自定义域名 + */ + @Schema(description = "自定义域名") + private String domain; + + /** + * 描述 + */ + @Schema(description = "描述") + private String description; + + /** + * 是否为默认存储 + */ + @Schema(description = "是否为默认存储") + @NotNull(message = "是否为默认存储不能为空") + private Boolean isDefault; + + /** + * 排序 + */ + @Schema(description = "排序") + private Integer sort; + + /** + * 状态 + */ + @Schema(description = "状态(1:启用;2:禁用)", type = "Integer", allowableValues = {"1", "2"}, example = "1") + private DisEnableStatusEnum status; +} \ No newline at end of file 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 new file mode 100644 index 00000000..e5b21d5d --- /dev/null +++ b/continew-admin-system/src/main/java/top/charles7c/continew/admin/system/model/resp/StorageDetailResp.java @@ -0,0 +1,120 @@ +/* + * 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.model.resp; + +import java.io.Serial; + +import lombok.Data; + +import io.swagger.v3.oas.annotations.media.Schema; + +import com.alibaba.excel.annotation.ExcelIgnoreUnannotated; +import com.alibaba.excel.annotation.ExcelProperty; + +import top.charles7c.continew.starter.extension.crud.base.BaseDetailResp; + +/** + * 存储库详情信息 + * + * @author Charles7c + * @since 2023/12/26 22:09 + */ +@Data +@ExcelIgnoreUnannotated +@Schema(description = "存储库详情信息") +public class StorageDetailResp extends BaseDetailResp { + + @Serial + private static final long serialVersionUID = 1L; + + /** + * 名称 + */ + @Schema(description = "名称") + @ExcelProperty(value = "名称") + private String name; + + /** + * 编码 + */ + @Schema(description = "编码") + @ExcelProperty(value = "编码") + private String code; + + /** + * Access Key + */ + @Schema(description = "Access Key") + @ExcelProperty(value = "Access Key") + private String accessKey; + + /** + * Secret Key + */ + @Schema(description = "Secret Key") + @ExcelProperty(value = "Secret Key") + private String secretKey; + + /** + * Endpoint + */ + @Schema(description = "Endpoint") + @ExcelProperty(value = "Endpoint") + private String endpoint; + + /** + * 桶名称 + */ + @Schema(description = "桶名称") + @ExcelProperty(value = "桶名称") + private String bucketName; + + /** + * 自定义域名 + */ + @Schema(description = "自定义域名") + @ExcelProperty(value = "自定义域名") + private String domain; + + /** + * 描述 + */ + @Schema(description = "描述") + @ExcelProperty(value = "描述") + private String description; + + /** + * 是否为默认存储 + */ + @Schema(description = "是否为默认存储") + @ExcelProperty(value = "是否为默认存储") + private Boolean isDefault; + + /** + * 排序 + */ + @Schema(description = "排序") + @ExcelProperty(value = "排序") + private Integer sort; + + /** + * 状态 + */ + @Schema(description = "状态") + @ExcelProperty(value = "状态") + private Integer status; +} \ No newline at end of file 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 new file mode 100644 index 00000000..97cfc30b --- /dev/null +++ b/continew-admin-system/src/main/java/top/charles7c/continew/admin/system/model/resp/StorageResp.java @@ -0,0 +1,105 @@ +/* + * 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.model.resp; + +import java.io.Serial; + +import lombok.Data; + +import io.swagger.v3.oas.annotations.media.Schema; + +import top.charles7c.continew.starter.extension.crud.base.BaseResp; + +/** + * 存储库信息 + * + * @author Charles7c + * @since 2023/12/26 22:09 + */ +@Data +@Schema(description = "存储库信息") +public class StorageResp extends BaseResp { + + @Serial + private static final long serialVersionUID = 1L; + + /** + * 名称 + */ + @Schema(description = "名称") + private String name; + + /** + * 编码 + */ + @Schema(description = "编码") + private String code; + + /** + * Access Key + */ + @Schema(description = "Access Key") + private String accessKey; + + /** + * Secret Key + */ + @Schema(description = "Secret Key") + private String secretKey; + + /** + * Endpoint + */ + @Schema(description = "Endpoint") + private String endpoint; + + /** + * 桶名称 + */ + @Schema(description = "桶名称") + private String bucketName; + + /** + * 自定义域名 + */ + @Schema(description = "自定义域名") + private String domain; + + /** + * 描述 + */ + @Schema(description = "描述") + private String description; + + /** + * 是否为默认存储 + */ + @Schema(description = "是否为默认存储") + private Boolean isDefault; + + /** + * 排序 + */ + @Schema(description = "排序") + private Integer sort; + + /** + * 状态 + */ + @Schema(description = "状态") + private Integer status; +} \ No newline at end of file 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 7df68656..3bbe45c9 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 @@ -16,6 +16,10 @@ package top.charles7c.continew.admin.system.service; +import java.util.List; + +import org.springframework.web.multipart.MultipartFile; + import top.charles7c.continew.admin.system.model.query.FileQuery; import top.charles7c.continew.admin.system.model.req.FileReq; import top.charles7c.continew.admin.system.model.resp.FileDetailResp; @@ -28,4 +32,24 @@ import top.charles7c.continew.starter.extension.crud.base.BaseService; * @author Charles7c * @since 2023/12/23 10:38 */ -public interface FileService extends BaseService {} \ No newline at end of file +public interface FileService extends BaseService { + + /** + * 上传 + * + * @param file + * 文件信息 + * @param storageCode + * 存储库编码 + */ + void upload(MultipartFile file, String storageCode); + + /** + * 根据存储库 ID 列表查询 + * + * @param storageIds + * 存储库 ID 列表 + * @return 文件数量 + */ + Long countByStorageIds(List storageIds); +} \ No newline at end of file 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 new file mode 100644 index 00000000..ab0cdbf7 --- /dev/null +++ b/continew-admin-system/src/main/java/top/charles7c/continew/admin/system/service/StorageService.java @@ -0,0 +1,49 @@ +/* + * 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.service; + +import top.charles7c.continew.admin.system.model.entity.StorageDO; +import top.charles7c.continew.admin.system.model.query.StorageQuery; +import top.charles7c.continew.admin.system.model.req.StorageReq; +import top.charles7c.continew.admin.system.model.resp.StorageDetailResp; +import top.charles7c.continew.admin.system.model.resp.StorageResp; +import top.charles7c.continew.starter.extension.crud.base.BaseService; + +/** + * 存储库业务接口 + * + * @author Charles7c + * @since 2023/12/26 22:09 + */ +public interface StorageService extends BaseService { + + /** + * 查询默认存储库 + * + * @return 存储库信息 + */ + StorageDO getDefaultStorage(); + + /** + * 根据编码查询 + * + * @param code + * 编码 + * @return 存储库信息 + */ + StorageDO getByCode(String code); +} \ No newline at end of file diff --git a/continew-admin-system/src/main/java/top/charles7c/continew/admin/system/service/impl/FileServiceImpl.java b/continew-admin-system/src/main/java/top/charles7c/continew/admin/system/service/impl/FileServiceImpl.java index 7bc9f411..79f646c4 100644 --- a/continew-admin-system/src/main/java/top/charles7c/continew/admin/system/service/impl/FileServiceImpl.java +++ b/continew-admin-system/src/main/java/top/charles7c/continew/admin/system/service/impl/FileServiceImpl.java @@ -16,17 +16,29 @@ package top.charles7c.continew.admin.system.service.impl; -import lombok.RequiredArgsConstructor; +import java.util.List; +import jakarta.annotation.Resource; + +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; + +import org.dromara.x.file.storage.core.*; import org.springframework.stereotype.Service; +import org.springframework.web.multipart.MultipartFile; + +import cn.hutool.core.util.StrUtil; import top.charles7c.continew.admin.system.mapper.FileMapper; import top.charles7c.continew.admin.system.model.entity.FileDO; +import top.charles7c.continew.admin.system.model.entity.StorageDO; import top.charles7c.continew.admin.system.model.query.FileQuery; import top.charles7c.continew.admin.system.model.req.FileReq; import top.charles7c.continew.admin.system.model.resp.FileDetailResp; import top.charles7c.continew.admin.system.model.resp.FileResp; import top.charles7c.continew.admin.system.service.FileService; +import top.charles7c.continew.admin.system.service.StorageService; +import top.charles7c.continew.starter.core.util.validate.CheckUtils; import top.charles7c.continew.starter.extension.crud.base.BaseServiceImpl; /** @@ -35,7 +47,45 @@ import top.charles7c.continew.starter.extension.crud.base.BaseServiceImpl; * @author Charles7c * @since 2023/12/23 10:38 */ +@Slf4j @Service @RequiredArgsConstructor public class FileServiceImpl extends BaseServiceImpl - implements FileService {} \ No newline at end of file + implements FileService { + + @Resource + private StorageService storageService; + private final FileStorageService fileStorageService; + + @Override + public void upload(MultipartFile file, String storageCode) { + if (StrUtil.isBlank(storageCode)) { + StorageDO storage = storageService.getDefaultStorage(); + CheckUtils.throwIfNull(storage, "请先指定默认存储库"); + storageCode = storage.getCode(); + } + UploadPretreatment uploadPretreatment = fileStorageService.of(file).setPlatform(storageCode); + uploadPretreatment.setProgressMonitor(new ProgressListener() { + @Override + public void start() { + log.info("开始上传"); + } + + @Override + public void progress(long progressSize, long allSize) { + log.info("已上传 [{}],总大小 [{}]", progressSize, allSize); + } + + @Override + public void finish() { + log.info("上传结束"); + } + }); + uploadPretreatment.upload(); + } + + @Override + public Long countByStorageIds(List storageIds) { + return baseMapper.lambdaQuery().in(FileDO::getStorageId, storageIds).count(); + } +} \ No newline at end of file diff --git a/continew-admin-system/src/main/java/top/charles7c/continew/admin/system/service/impl/StorageServiceImpl.java b/continew-admin-system/src/main/java/top/charles7c/continew/admin/system/service/impl/StorageServiceImpl.java new file mode 100644 index 00000000..d0cc55b2 --- /dev/null +++ b/continew-admin-system/src/main/java/top/charles7c/continew/admin/system/service/impl/StorageServiceImpl.java @@ -0,0 +1,185 @@ +/* + * 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.service.impl; + +import java.util.Collections; +import java.util.List; +import java.util.Map; +import java.util.concurrent.CopyOnWriteArrayList; + +import jakarta.annotation.Resource; +import jakarta.servlet.ServletContext; + +import lombok.RequiredArgsConstructor; + +import org.dromara.x.file.storage.core.FileStorageProperties; +import org.dromara.x.file.storage.core.FileStorageService; +import org.dromara.x.file.storage.core.FileStorageServiceBuilder; +import org.dromara.x.file.storage.core.platform.FileStorage; +import org.springframework.context.ApplicationContext; +import org.springframework.stereotype.Service; +import org.springframework.web.accept.ContentNegotiationManager; +import org.springframework.web.servlet.HandlerMapping; +import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry; +import org.springframework.web.servlet.handler.SimpleUrlHandlerMapping; +import org.springframework.web.util.UrlPathHelper; + +import cn.hutool.core.util.ReflectUtil; +import cn.hutool.core.util.StrUtil; + +import top.charles7c.continew.admin.common.enums.DisEnableStatusEnum; +import top.charles7c.continew.admin.system.mapper.StorageMapper; +import top.charles7c.continew.admin.system.model.entity.StorageDO; +import top.charles7c.continew.admin.system.model.query.StorageQuery; +import top.charles7c.continew.admin.system.model.req.StorageReq; +import top.charles7c.continew.admin.system.model.resp.StorageDetailResp; +import top.charles7c.continew.admin.system.model.resp.StorageResp; +import top.charles7c.continew.admin.system.service.FileService; +import top.charles7c.continew.admin.system.service.StorageService; +import top.charles7c.continew.starter.core.util.validate.CheckUtils; +import top.charles7c.continew.starter.extension.crud.base.BaseServiceImpl; + +/** + * 存储库业务实现 + * + * @author Charles7c + * @since 2023/12/26 22:09 + */ +@Service +@RequiredArgsConstructor +public class StorageServiceImpl + extends BaseServiceImpl + implements StorageService { + + 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); + return super.add(req); + } + + @Override + public void update(StorageReq req, Long id) { + String code = req.getCode(); + CheckUtils.throwIf(this.isCodeExists(code, id), "修改失败,[{}] 已存在", code); + StorageDO oldStorage = super.getById(id); + CheckUtils.throwIf( + Boolean.TRUE.equals(oldStorage.getIsDefault()) && DisEnableStatusEnum.DISABLE.equals(req.getStatus()), + "[{}] 是默认存储库,不允许禁用", oldStorage.getName()); + this.loadFileStorage(req); + super.update(req, id); + } + + @Override + 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())); + super.delete(ids); + } + + @Override + public StorageDO getDefaultStorage() { + return baseMapper.lambdaQuery().eq(StorageDO::getIsDefault, true).one(); + } + + @Override + public StorageDO getByCode(String code) { + return baseMapper.lambdaQuery().eq(StorageDO::getCode, code).one(); + } + + /** + * 加载存储配置 + * + * @param req + * 存储配置信息 + */ + private void loadFileStorage(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))); + } + + /** + * 移除存储配置 + * + * @param code + * 存储配置编码 + */ + private void removeFileStorage(String code) { + CopyOnWriteArrayList fileStorageList = fileStorageService.getFileStorageList(); + FileStorage fileStorage = fileStorageService.getFileStorage(code); + fileStorageList.remove(fileStorage); + fileStorage.close(); + } + + /** + * 编码是否存在 + * + * @param code + * 编码 + * @param id + * ID + * @return 是否存在 + */ + private boolean isCodeExists(String code, Long id) { + return baseMapper.lambdaQuery().eq(StorageDO::getCode, code).ne(null != id, StorageDO::getId, id).exists(); + } + + /** + * 注册静态资源映射 + * + * @param registerMapping + * 静态资源映射列表 + */ + private void registerResource(Map registerMapping) { + final UrlPathHelper urlPathHelper = applicationContext.getBean("mvcUrlPathHelper", UrlPathHelper.class); + final ContentNegotiationManager contentNegotiationManager = + applicationContext.getBean("mvcContentNegotiationManager", ContentNegotiationManager.class); + final ServletContext servletContext = applicationContext.getBean(ServletContext.class); + final HandlerMapping resourceHandlerMapping = + applicationContext.getBean("resourceHandlerMapping", HandlerMapping.class); + // 已经注册的静态资源映射 + final Map handlerMap = + (Map)ReflectUtil.getFieldValue(resourceHandlerMapping, "handlerMap"); + final ResourceHandlerRegistry resourceHandlerRegistry = + new ResourceHandlerRegistry(applicationContext, servletContext, contentNegotiationManager, urlPathHelper); + // 重新注册静态资源映射 + for (Map.Entry entry : registerMapping.entrySet()) { + String pathPattern = StrUtil.appendIfMissing(entry.getKey(), "/**"); + String resourceLocations = StrUtil.appendIfMissing(entry.getValue(), "/"); + // 移除之前注册过的 + handlerMap.remove(pathPattern); + // 重新注册 + resourceHandlerRegistry.addResourceHandler(pathPattern).addResourceLocations("file:" + resourceLocations); + } + final Map additionalUrlMap = + ReflectUtil.invoke(resourceHandlerRegistry, "getHandlerMapping").getUrlMap(); + ReflectUtil.invoke(resourceHandlerMapping, "registerHandlers", additionalUrlMap); + } +} \ No newline at end of file diff --git a/continew-admin-webapi/src/main/java/top/charles7c/continew/admin/ContiNewAdminApplication.java b/continew-admin-webapi/src/main/java/top/charles7c/continew/admin/ContiNewAdminApplication.java index 00889ea2..ab1ed1bb 100644 --- a/continew-admin-webapi/src/main/java/top/charles7c/continew/admin/ContiNewAdminApplication.java +++ b/continew-admin-webapi/src/main/java/top/charles7c/continew/admin/ContiNewAdminApplication.java @@ -23,6 +23,7 @@ import lombok.extern.slf4j.Slf4j; import io.swagger.v3.oas.annotations.Hidden; +import org.dromara.x.file.storage.spring.EnableFileStorage; import org.springframework.boot.ApplicationArguments; import org.springframework.boot.ApplicationRunner; import org.springframework.boot.SpringApplication; @@ -44,6 +45,7 @@ import top.charles7c.continew.starter.core.autoconfigure.project.ProjectProperti * @since 2022/12/8 23:15 */ @Slf4j +@EnableFileStorage @RestController @SpringBootApplication @RequiredArgsConstructor diff --git a/continew-admin-webapi/src/main/java/top/charles7c/continew/admin/webapi/system/StorageController.java b/continew-admin-webapi/src/main/java/top/charles7c/continew/admin/webapi/system/StorageController.java new file mode 100644 index 00000000..86cfdb9f --- /dev/null +++ b/continew-admin-webapi/src/main/java/top/charles7c/continew/admin/webapi/system/StorageController.java @@ -0,0 +1,41 @@ +/* + * 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.webapi.system; + +import io.swagger.v3.oas.annotations.tags.Tag; + +import org.springframework.web.bind.annotation.*; + +import top.charles7c.continew.admin.system.model.query.StorageQuery; +import top.charles7c.continew.admin.system.model.req.StorageReq; +import top.charles7c.continew.admin.system.model.resp.StorageDetailResp; +import top.charles7c.continew.admin.system.model.resp.StorageResp; +import top.charles7c.continew.admin.system.service.StorageService; +import top.charles7c.continew.starter.extension.crud.annotation.CrudRequestMapping; +import top.charles7c.continew.starter.extension.crud.base.BaseController; + +/** + * 存储库管理 API + * + * @author Charles7c + * @since 2023/12/26 22:09 + */ +@Tag(name = "存储库管理 API") +@RestController +@CrudRequestMapping("/system/storage") +public class StorageController + extends BaseController {} \ 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 f6b62ada..efd4c0b7 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 @@ -12,8 +12,8 @@ CREATE TABLE IF NOT EXISTS `sys_file` ( `storage_id` bigint(20) NOT NULL COMMENT '存储库ID', `create_user` bigint(20) NOT NULL COMMENT '创建人', `create_time` datetime NOT NULL COMMENT '创建时间', - `update_user` bigint(20) DEFAULT NULL COMMENT '修改人', - `update_time` datetime DEFAULT NULL COMMENT '修改时间', + `update_user` bigint(20) NOT NULL COMMENT '修改人', + `update_time` datetime NOT NULL COMMENT '修改时间', PRIMARY KEY (`id`) USING BTREE, INDEX `idx_type`(`type`) USING BTREE, INDEX `idx_create_user`(`create_user`) USING BTREE,