diff --git a/snowy-common/src/main/java/vip/xiaonuo/common/mapper/CommonDeleteAbsoluteMapper.java b/snowy-common/src/main/java/vip/xiaonuo/common/mapper/CommonDeleteAbsoluteMapper.java new file mode 100644 index 00000000..c978c77b --- /dev/null +++ b/snowy-common/src/main/java/vip/xiaonuo/common/mapper/CommonDeleteAbsoluteMapper.java @@ -0,0 +1,35 @@ +/* + * Copyright [2022] [https://www.xiaonuo.vip] + * + * Snowy采用APACHE LICENSE 2.0开源协议,您在使用过程中,需要注意以下几点: + * + * 1.请不要删除和修改根目录下的LICENSE文件。 + * 2.请不要删除和修改Snowy源码头部的版权声明。 + * 3.本项目代码可免费商业使用,商业使用请保留源码和相关描述文件的项目出处,作者声明等。 + * 4.分发源码时候,请注明软件出处 https://www.xiaonuo.vip + * 5.不可二次分发开源参与同类竞品,如有想法可联系团队xiaonuobase@qq.com商议合作。 + * 6.若您的项目无法满足以上几点,需要更多功能代码,获取Snowy商业授权许可,请在官网购买授权,地址为 https://www.xiaonuo.vip + */ +package vip.xiaonuo.common.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; + +import java.io.Serializable; + +/** + * 通用物理删除Mapper,实现此Mapper并调用此方法可实现物理删除数据 + * + * @author xuyuxiang + * @date 2023/3/3 10:14 + **/ +public interface CommonDeleteAbsoluteMapper extends BaseMapper { + + /** + * 物理删除 + * + * @param id 主键 + * @return int + */ + @SuppressWarnings("ALL") + int deleteAbsoluteById(Serializable id); +} diff --git a/snowy-plugin-api/snowy-plugin-dev-api/src/main/java/vip/xiaonuo/dev/api/DevFileApi.java b/snowy-plugin-api/snowy-plugin-dev-api/src/main/java/vip/xiaonuo/dev/api/DevFileApi.java index 991339f9..e0a20d28 100644 --- a/snowy-plugin-api/snowy-plugin-dev-api/src/main/java/vip/xiaonuo/dev/api/DevFileApi.java +++ b/snowy-plugin-api/snowy-plugin-dev-api/src/main/java/vip/xiaonuo/dev/api/DevFileApi.java @@ -23,6 +23,14 @@ import org.springframework.web.multipart.MultipartFile; **/ public interface DevFileApi { + /** + * 动态上传文件返回id(使用系统配置的默认文件引擎) + * + * @author xuyuxiang + * @date 2021/10/13 14:01 + **/ + String uploadDynamicReturnId(MultipartFile file); + /* =========本地文件========= */ /** @@ -110,4 +118,12 @@ public interface DevFileApi { * @date 2024/7/26 16:10 */ JSONObject getFileInfoById(String id); + + /** + * 根据文件id物理删除文件 + * + * @author xuyuxiang + * @date 2022/8/4 10:36 + **/ + void deleteAbsoluteById(String id); } diff --git a/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/file/entity/DevFile.java b/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/file/entity/DevFile.java index b37b53a7..1a456d33 100644 --- a/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/file/entity/DevFile.java +++ b/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/file/entity/DevFile.java @@ -41,6 +41,10 @@ public class DevFile extends CommonEntity { @Schema(description = "存储桶") private String bucket; + /** 文件Key */ + @Schema(description = "文件Key") + private String fileKey; + /** 文件名称 */ @Schema(description = "文件名称") private String name; diff --git a/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/file/mapper/DevFileMapper.java b/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/file/mapper/DevFileMapper.java index c2b67f78..1616472e 100644 --- a/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/file/mapper/DevFileMapper.java +++ b/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/file/mapper/DevFileMapper.java @@ -12,7 +12,7 @@ */ package vip.xiaonuo.dev.modular.file.mapper; -import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import vip.xiaonuo.common.mapper.CommonDeleteAbsoluteMapper; import vip.xiaonuo.dev.modular.file.entity.DevFile; /** @@ -21,5 +21,5 @@ import vip.xiaonuo.dev.modular.file.entity.DevFile; * @author xuyuxiang * @date 2022/2/23 18:40 **/ -public interface DevFileMapper extends BaseMapper { +public interface DevFileMapper extends CommonDeleteAbsoluteMapper { } diff --git a/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/file/provider/DevFileApiProvider.java b/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/file/provider/DevFileApiProvider.java index 20efcec8..4b25f3fe 100644 --- a/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/file/provider/DevFileApiProvider.java +++ b/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/file/provider/DevFileApiProvider.java @@ -17,8 +17,10 @@ import cn.hutool.json.JSONUtil; import jakarta.annotation.Resource; import org.springframework.stereotype.Service; import org.springframework.web.multipart.MultipartFile; +import vip.xiaonuo.dev.api.DevConfigApi; import vip.xiaonuo.dev.api.DevFileApi; import vip.xiaonuo.dev.modular.file.enums.DevFileEngineTypeEnum; +import vip.xiaonuo.dev.modular.file.param.DevFileIdParam; import vip.xiaonuo.dev.modular.file.service.DevFileService; import java.util.Optional; @@ -32,9 +34,20 @@ import java.util.Optional; @Service public class DevFileApiProvider implements DevFileApi { + /** 默认文件引擎 */ + private static final String SNOWY_SYS_DEFAULT_FILE_ENGINE_KEY = "SNOWY_SYS_DEFAULT_FILE_ENGINE"; + @Resource private DevFileService devFileService; + @Resource + private DevConfigApi devConfigApi; + + @Override + public String uploadDynamicReturnId(MultipartFile file) { + return devFileService.uploadReturnId(devConfigApi.getValueByKey(SNOWY_SYS_DEFAULT_FILE_ENGINE_KEY), file); + } + @Override public String storageFileWithReturnUrlLocal(MultipartFile file) { return devFileService.uploadReturnUrl(DevFileEngineTypeEnum.LOCAL.getValue(), file); @@ -81,4 +94,11 @@ public class DevFileApiProvider implements DevFileApi { .map(JSONUtil::parseObj) .orElse(new JSONObject()); } + + @Override + public void deleteAbsoluteById(String id) { + DevFileIdParam devFileIdParam = new DevFileIdParam(); + devFileIdParam.setId(id); + devFileService.deleteAbsolute(devFileIdParam); + } } diff --git a/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/file/service/DevFileService.java b/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/file/service/DevFileService.java index fe3720fd..fc2e6041 100644 --- a/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/file/service/DevFileService.java +++ b/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/file/service/DevFileService.java @@ -81,6 +81,14 @@ public interface DevFileService extends IService { **/ void delete(List devFileIdParamList); + /** + * 物理删除文件 + * + * @author xuyuxiang + * @date 2022/8/4 10:36 + **/ + void deleteAbsolute(DevFileIdParam devFileIdParam); + /** * 获取文件详情 * diff --git a/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/file/service/impl/DevFileServiceImpl.java b/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/file/service/impl/DevFileServiceImpl.java index bd5151b0..c6360197 100644 --- a/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/file/service/impl/DevFileServiceImpl.java +++ b/snowy-plugin/snowy-plugin-dev/src/main/java/vip/xiaonuo/dev/modular/file/service/impl/DevFileServiceImpl.java @@ -28,7 +28,9 @@ import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import jakarta.annotation.Resource; import jakarta.servlet.http.HttpServletResponse; +import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; import org.springframework.web.multipart.MultipartFile; import vip.xiaonuo.common.exception.CommonException; import vip.xiaonuo.common.page.CommonPageRequest; @@ -60,6 +62,7 @@ import java.util.List; * @author xuyuxiang * @date 2022/2/23 18:43 **/ +@Slf4j @Service public class DevFileServiceImpl extends ServiceImpl implements DevFileService { @@ -122,10 +125,40 @@ public class DevFileServiceImpl extends ServiceImpl impl } @Override + @Transactional(rollbackFor = Exception.class) public void delete(List devFileIdParamList) { this.removeByIds(CollStreamUtil.toList(devFileIdParamList, DevFileIdParam::getId)); } + @Override + public void deleteAbsolute(DevFileIdParam devFileIdParam) { + DevFile devFile = this.queryEntity(devFileIdParam.getId()); + try { + // 存储引擎 + String engine = devFile.getEngine(); + // 存储桶名称 + String bucketName = devFile.getBucket(); + // 文件key + String fileKey = devFile.getFileKey(); + // 根据存储引擎删除文件 + if (DevFileEngineTypeEnum.LOCAL.getValue().equals(engine)) { + DevFileLocalUtil.deleteFile(bucketName, fileKey); + } else if (DevFileEngineTypeEnum.ALIYUN.getValue().equals(engine)) { + DevFileAliyunUtil.deleteFile(bucketName, fileKey); + } else if (DevFileEngineTypeEnum.TENCENT.getValue().equals(engine)) { + DevFileTencentUtil.deleteFile(bucketName, fileKey); + } else if (DevFileEngineTypeEnum.MINIO.getValue().equals(engine)) { + DevFileMinIoUtil.deleteFile(bucketName, fileKey); + } else { + log.error("未知存储引擎:{}", engine); + } + } catch (Exception e) { + log.error("文件删除失败:{},路径:{}", devFile.getName(), devFile.getStoragePath(), e); + throw new CommonException("文件删除失败"); // 触发事务回滚 + } + this.baseMapper.deleteAbsoluteById(devFile.getId()); + } + /** * 存储文件 * diff --git a/snowy-web-app/src/main/resources/_sql/snowy_mysql.sql b/snowy-web-app/src/main/resources/_sql/snowy_mysql.sql index 9e5fa12a..40a12dab 100644 --- a/snowy-web-app/src/main/resources/_sql/snowy_mysql.sql +++ b/snowy-web-app/src/main/resources/_sql/snowy_mysql.sql @@ -403,6 +403,7 @@ CREATE TABLE `DEV_FILE` ( `ID` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, `ENGINE` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '存储引擎', `BUCKET` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '存储桶', + `FILE_KEY` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '文件KEY', `NAME` text CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL COMMENT '文件名称', `SUFFIX` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '文件后缀', `SIZE_KB` bigint(20) NULL DEFAULT NULL COMMENT '文件大小kb',