From 05d4aae65d624ba08935792f64f33468f199b77f Mon Sep 17 00:00:00 2001 From: YunaiV Date: Mon, 14 Mar 2022 23:07:37 +0800 Subject: [PATCH] 完成 yudao-spring-boot-starter-file 组件,支持 S3 对接云存储、local、ftp、sftp、db 等协议 --- yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/config/YudaoPayAutoConfiguration.java | 1 + yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/PayClientFactoryImpl.java | 10 +++++----- yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/enums/PayChannelEnum.java | 1 - yudao-framework/yudao-spring-boot-starter-file/src/main/java/cn/iocoder/yudao/framework/file/config/YudaoFileAutoConfiguration.java | 21 +++++++++++++++++++++ yudao-framework/yudao-spring-boot-starter-file/src/main/java/cn/iocoder/yudao/framework/file/core/client/AbstractFileClient.java | 71 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ yudao-framework/yudao-spring-boot-starter-file/src/main/java/cn/iocoder/yudao/framework/file/core/client/FileClientFactory.java | 22 ++++++++++++++++++++++ yudao-framework/yudao-spring-boot-starter-file/src/main/java/cn/iocoder/yudao/framework/file/core/client/FileClientFactoryImpl.java | 69 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ yudao-framework/yudao-spring-boot-starter-file/src/main/java/cn/iocoder/yudao/framework/file/core/client/db/DBFileClient.java | 41 +++++++++++++++++++++++++++++++++++++++++ yudao-framework/yudao-spring-boot-starter-file/src/main/java/cn/iocoder/yudao/framework/file/core/client/db/DBFileClientConfig.java | 24 ++++++++++++++++++++++++ yudao-framework/yudao-spring-boot-starter-file/src/main/java/cn/iocoder/yudao/framework/file/core/client/db/DBFileContentFrameworkDAO.java | 16 ++++++++++++++++ yudao-framework/yudao-spring-boot-starter-file/src/main/java/cn/iocoder/yudao/framework/file/core/client/ftp/FtpFileClient.java | 73 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ yudao-framework/yudao-spring-boot-starter-file/src/main/java/cn/iocoder/yudao/framework/file/core/client/ftp/FtpFileClientConfig.java | 59 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ yudao-framework/yudao-spring-boot-starter-file/src/main/java/cn/iocoder/yudao/framework/file/core/client/impl/AbstractFileClient.java | 71 ----------------------------------------------------------------------- yudao-framework/yudao-spring-boot-starter-file/src/main/java/cn/iocoder/yudao/framework/file/core/client/impl/ftp/FtpFileClient.java | 73 ------------------------------------------------------------------------- yudao-framework/yudao-spring-boot-starter-file/src/main/java/cn/iocoder/yudao/framework/file/core/client/impl/ftp/FtpFileClientConfig.java | 59 ----------------------------------------------------------- yudao-framework/yudao-spring-boot-starter-file/src/main/java/cn/iocoder/yudao/framework/file/core/client/impl/local/LocalFileClient.java | 52 ---------------------------------------------------- yudao-framework/yudao-spring-boot-starter-file/src/main/java/cn/iocoder/yudao/framework/file/core/client/impl/local/LocalFileClientConfig.java | 30 ------------------------------ yudao-framework/yudao-spring-boot-starter-file/src/main/java/cn/iocoder/yudao/framework/file/core/client/impl/s3/S3FileClient.java | 103 ------------------------------------------------------------------------------------------------------- yudao-framework/yudao-spring-boot-starter-file/src/main/java/cn/iocoder/yudao/framework/file/core/client/impl/s3/S3FileClientConfig.java | 83 ----------------------------------------------------------------------------------- yudao-framework/yudao-spring-boot-starter-file/src/main/java/cn/iocoder/yudao/framework/file/core/client/impl/s3/S3ModifyPathInterceptor.java | 36 ------------------------------------ yudao-framework/yudao-spring-boot-starter-file/src/main/java/cn/iocoder/yudao/framework/file/core/client/impl/sftp/SftpFileClient.java | 61 ------------------------------------------------------------- yudao-framework/yudao-spring-boot-starter-file/src/main/java/cn/iocoder/yudao/framework/file/core/client/impl/sftp/SftpFileClientConfig.java | 52 ---------------------------------------------------- yudao-framework/yudao-spring-boot-starter-file/src/main/java/cn/iocoder/yudao/framework/file/core/client/local/LocalFileClient.java | 52 ++++++++++++++++++++++++++++++++++++++++++++++++++++ yudao-framework/yudao-spring-boot-starter-file/src/main/java/cn/iocoder/yudao/framework/file/core/client/local/LocalFileClientConfig.java | 30 ++++++++++++++++++++++++++++++ yudao-framework/yudao-spring-boot-starter-file/src/main/java/cn/iocoder/yudao/framework/file/core/client/s3/S3FileClient.java | 103 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ yudao-framework/yudao-spring-boot-starter-file/src/main/java/cn/iocoder/yudao/framework/file/core/client/s3/S3FileClientConfig.java | 83 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ yudao-framework/yudao-spring-boot-starter-file/src/main/java/cn/iocoder/yudao/framework/file/core/client/s3/S3ModifyPathInterceptor.java | 36 ++++++++++++++++++++++++++++++++++++ yudao-framework/yudao-spring-boot-starter-file/src/main/java/cn/iocoder/yudao/framework/file/core/client/sftp/SftpFileClient.java | 61 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ yudao-framework/yudao-spring-boot-starter-file/src/main/java/cn/iocoder/yudao/framework/file/core/client/sftp/SftpFileClientConfig.java | 52 ++++++++++++++++++++++++++++++++++++++++++++++++++++ yudao-framework/yudao-spring-boot-starter-file/src/main/java/cn/iocoder/yudao/framework/file/core/enums/FileStorageEnum.java | 55 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ yudao-framework/yudao-spring-boot-starter-file/src/main/resources/META-INF/spring.factories | 2 ++ yudao-framework/yudao-spring-boot-starter-file/src/test/java/cn/iocoder/yudao/framework/file/core/client/ftp/FtpFileClientTest.java | 2 -- yudao-framework/yudao-spring-boot-starter-file/src/test/java/cn/iocoder/yudao/framework/file/core/client/local/LocalFileClientTest.java | 2 -- yudao-framework/yudao-spring-boot-starter-file/src/test/java/cn/iocoder/yudao/framework/file/core/client/package-info.java | 4 ---- yudao-framework/yudao-spring-boot-starter-file/src/test/java/cn/iocoder/yudao/framework/file/core/client/s3/S3FileClientTest.java | 2 -- yudao-framework/yudao-spring-boot-starter-file/src/test/java/cn/iocoder/yudao/framework/file/core/client/sftp/SftpFileClientTest.java | 2 -- 36 files changed, 876 insertions(+), 638 deletions(-) create mode 100644 yudao-framework/yudao-spring-boot-starter-file/src/main/java/cn/iocoder/yudao/framework/file/config/YudaoFileAutoConfiguration.java create mode 100644 yudao-framework/yudao-spring-boot-starter-file/src/main/java/cn/iocoder/yudao/framework/file/core/client/AbstractFileClient.java create mode 100644 yudao-framework/yudao-spring-boot-starter-file/src/main/java/cn/iocoder/yudao/framework/file/core/client/FileClientFactory.java create mode 100644 yudao-framework/yudao-spring-boot-starter-file/src/main/java/cn/iocoder/yudao/framework/file/core/client/FileClientFactoryImpl.java create mode 100644 yudao-framework/yudao-spring-boot-starter-file/src/main/java/cn/iocoder/yudao/framework/file/core/client/db/DBFileClient.java create mode 100644 yudao-framework/yudao-spring-boot-starter-file/src/main/java/cn/iocoder/yudao/framework/file/core/client/db/DBFileClientConfig.java create mode 100644 yudao-framework/yudao-spring-boot-starter-file/src/main/java/cn/iocoder/yudao/framework/file/core/client/db/DBFileContentFrameworkDAO.java create mode 100644 yudao-framework/yudao-spring-boot-starter-file/src/main/java/cn/iocoder/yudao/framework/file/core/client/ftp/FtpFileClient.java create mode 100644 yudao-framework/yudao-spring-boot-starter-file/src/main/java/cn/iocoder/yudao/framework/file/core/client/ftp/FtpFileClientConfig.java delete mode 100644 yudao-framework/yudao-spring-boot-starter-file/src/main/java/cn/iocoder/yudao/framework/file/core/client/impl/AbstractFileClient.java delete mode 100644 yudao-framework/yudao-spring-boot-starter-file/src/main/java/cn/iocoder/yudao/framework/file/core/client/impl/ftp/FtpFileClient.java delete mode 100644 yudao-framework/yudao-spring-boot-starter-file/src/main/java/cn/iocoder/yudao/framework/file/core/client/impl/ftp/FtpFileClientConfig.java delete mode 100644 yudao-framework/yudao-spring-boot-starter-file/src/main/java/cn/iocoder/yudao/framework/file/core/client/impl/local/LocalFileClient.java delete mode 100644 yudao-framework/yudao-spring-boot-starter-file/src/main/java/cn/iocoder/yudao/framework/file/core/client/impl/local/LocalFileClientConfig.java delete mode 100644 yudao-framework/yudao-spring-boot-starter-file/src/main/java/cn/iocoder/yudao/framework/file/core/client/impl/s3/S3FileClient.java delete mode 100644 yudao-framework/yudao-spring-boot-starter-file/src/main/java/cn/iocoder/yudao/framework/file/core/client/impl/s3/S3FileClientConfig.java delete mode 100644 yudao-framework/yudao-spring-boot-starter-file/src/main/java/cn/iocoder/yudao/framework/file/core/client/impl/s3/S3ModifyPathInterceptor.java delete mode 100644 yudao-framework/yudao-spring-boot-starter-file/src/main/java/cn/iocoder/yudao/framework/file/core/client/impl/sftp/SftpFileClient.java delete mode 100644 yudao-framework/yudao-spring-boot-starter-file/src/main/java/cn/iocoder/yudao/framework/file/core/client/impl/sftp/SftpFileClientConfig.java create mode 100644 yudao-framework/yudao-spring-boot-starter-file/src/main/java/cn/iocoder/yudao/framework/file/core/client/local/LocalFileClient.java create mode 100644 yudao-framework/yudao-spring-boot-starter-file/src/main/java/cn/iocoder/yudao/framework/file/core/client/local/LocalFileClientConfig.java create mode 100644 yudao-framework/yudao-spring-boot-starter-file/src/main/java/cn/iocoder/yudao/framework/file/core/client/s3/S3FileClient.java create mode 100644 yudao-framework/yudao-spring-boot-starter-file/src/main/java/cn/iocoder/yudao/framework/file/core/client/s3/S3FileClientConfig.java create mode 100644 yudao-framework/yudao-spring-boot-starter-file/src/main/java/cn/iocoder/yudao/framework/file/core/client/s3/S3ModifyPathInterceptor.java create mode 100644 yudao-framework/yudao-spring-boot-starter-file/src/main/java/cn/iocoder/yudao/framework/file/core/client/sftp/SftpFileClient.java create mode 100644 yudao-framework/yudao-spring-boot-starter-file/src/main/java/cn/iocoder/yudao/framework/file/core/client/sftp/SftpFileClientConfig.java create mode 100644 yudao-framework/yudao-spring-boot-starter-file/src/main/java/cn/iocoder/yudao/framework/file/core/enums/FileStorageEnum.java create mode 100644 yudao-framework/yudao-spring-boot-starter-file/src/main/resources/META-INF/spring.factories delete mode 100644 yudao-framework/yudao-spring-boot-starter-file/src/test/java/cn/iocoder/yudao/framework/file/core/client/package-info.java diff --git a/yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/config/YudaoPayAutoConfiguration.java b/yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/config/YudaoPayAutoConfiguration.java index d49c1c2..c4d41b6 100644 --- a/yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/config/YudaoPayAutoConfiguration.java +++ b/yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/config/YudaoPayAutoConfiguration.java @@ -11,6 +11,7 @@ import org.springframework.context.annotation.Configuration; * * @author 芋道源码 */ +@Configuration @EnableConfigurationProperties(PayProperties.class) public class YudaoPayAutoConfiguration { diff --git a/yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/PayClientFactoryImpl.java b/yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/PayClientFactoryImpl.java index edfd449..6471521 100644 --- a/yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/PayClientFactoryImpl.java +++ b/yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/PayClientFactoryImpl.java @@ -27,11 +27,11 @@ public class PayClientFactoryImpl implements PayClientFactory { * 支付客户端 Map * key:渠道编号 */ - private final ConcurrentMap> channelIdClients = new ConcurrentHashMap<>(); + private final ConcurrentMap> clients = new ConcurrentHashMap<>(); @Override public PayClient getPayClient(Long channelId) { - AbstractPayClient client = channelIdClients.get(channelId); + AbstractPayClient client = clients.get(channelId); if (client == null) { log.error("[getPayClient][渠道编号({}) 找不到客户端]", channelId); } @@ -42,11 +42,11 @@ public class PayClientFactoryImpl implements PayClientFactory { @SuppressWarnings("unchecked") public void createOrUpdatePayClient(Long channelId, String channelCode, Config config) { - AbstractPayClient client = (AbstractPayClient) channelIdClients.get(channelId); + AbstractPayClient client = (AbstractPayClient) clients.get(channelId); if (client == null) { client = this.createPayClient(channelId, channelCode, config); client.init(); - channelIdClients.put(client.getId(), client); + clients.put(client.getId(), client); } else { client.refresh(config); } @@ -69,7 +69,7 @@ public class PayClientFactoryImpl implements PayClientFactory { case ALIPAY_PC: return (AbstractPayClient) new AlipayQrPayClient(channelId, (AlipayPayClientConfig) config); } // 创建失败,错误日志 + 抛出异常 - log.error("[createSmsClient][配置({}) 找不到合适的客户端实现]", config); + log.error("[createPayClient][配置({}) 找不到合适的客户端实现]", config); throw new IllegalArgumentException(String.format("配置(%s) 找不到合适的客户端实现", config)); } diff --git a/yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/enums/PayChannelEnum.java b/yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/enums/PayChannelEnum.java index f8a4971..fccbab8 100644 --- a/yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/enums/PayChannelEnum.java +++ b/yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/enums/PayChannelEnum.java @@ -56,5 +56,4 @@ public enum PayChannelEnum { return ArrayUtil.firstMatch(o -> o.getCode().equals(code), values()); } - } diff --git a/yudao-framework/yudao-spring-boot-starter-file/src/main/java/cn/iocoder/yudao/framework/file/config/YudaoFileAutoConfiguration.java b/yudao-framework/yudao-spring-boot-starter-file/src/main/java/cn/iocoder/yudao/framework/file/config/YudaoFileAutoConfiguration.java new file mode 100644 index 0000000..5f7bd91 --- /dev/null +++ b/yudao-framework/yudao-spring-boot-starter-file/src/main/java/cn/iocoder/yudao/framework/file/config/YudaoFileAutoConfiguration.java @@ -0,0 +1,21 @@ +package cn.iocoder.yudao.framework.file.config; + +import cn.iocoder.yudao.framework.file.core.client.FileClientFactory; +import cn.iocoder.yudao.framework.file.core.client.FileClientFactoryImpl; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +/** + * 文件配置类 + * + * @author 芋道源码 + */ +@Configuration +public class YudaoFileAutoConfiguration { + + @Bean + public FileClientFactory fileClientFactory() { + return new FileClientFactoryImpl(); + } + +} diff --git a/yudao-framework/yudao-spring-boot-starter-file/src/main/java/cn/iocoder/yudao/framework/file/core/client/AbstractFileClient.java b/yudao-framework/yudao-spring-boot-starter-file/src/main/java/cn/iocoder/yudao/framework/file/core/client/AbstractFileClient.java new file mode 100644 index 0000000..262ceab --- /dev/null +++ b/yudao-framework/yudao-spring-boot-starter-file/src/main/java/cn/iocoder/yudao/framework/file/core/client/AbstractFileClient.java @@ -0,0 +1,71 @@ +package cn.iocoder.yudao.framework.file.core.client; + +import cn.hutool.core.util.StrUtil; +import cn.iocoder.yudao.framework.file.core.client.FileClient; +import cn.iocoder.yudao.framework.file.core.client.FileClientConfig; +import lombok.extern.slf4j.Slf4j; + +/** + * 文件客户端的抽象类,提供模板方法,减少子类的冗余代码 + * + * @author 芋道源码 + */ +@Slf4j +public abstract class AbstractFileClient implements FileClient { + + /** + * 配置编号 + */ + private final Long id; + /** + * 文件配置 + */ + protected Config config; + + public AbstractFileClient(Long id, Config config) { + this.id = id; + this.config = config; + } + + /** + * 初始化 + */ + public final void init() { + doInit(); + log.info("[init][配置({}) 初始化完成]", config); + } + + /** + * 自定义初始化 + */ + protected abstract void doInit(); + + public final void refresh(Config config) { + // 判断是否更新 + if (config.equals(this.config)) { + return; + } + log.info("[refresh][配置({})发生变化,重新初始化]", config); + this.config = config; + // 初始化 + this.init(); + } + + @Override + public Long getId() { + return id; + } + + /** + * 格式化文件的 URL 访问地址 + * 使用场景:local、ftp、db,通过 FileController 的 getFile 来获取文件内容 + * + * @param domain 自定义域名 + * @param path 文件路径 + * @return URL 访问地址 + */ + protected String formatFileUrl(String domain, String path) { + return StrUtil.format("{}/system-api/{}/get/{}", domain, getId(), path); + } + +} diff --git a/yudao-framework/yudao-spring-boot-starter-file/src/main/java/cn/iocoder/yudao/framework/file/core/client/FileClientFactory.java b/yudao-framework/yudao-spring-boot-starter-file/src/main/java/cn/iocoder/yudao/framework/file/core/client/FileClientFactory.java new file mode 100644 index 0000000..85b2176 --- /dev/null +++ b/yudao-framework/yudao-spring-boot-starter-file/src/main/java/cn/iocoder/yudao/framework/file/core/client/FileClientFactory.java @@ -0,0 +1,22 @@ +package cn.iocoder.yudao.framework.file.core.client; + +public interface FileClientFactory { + + /** + * 获得文件客户端 + * + * @param channelId 渠道编号 + * @return 文件客户端 + */ + FileClient getFileClient(Long channelId); + + /** + * 创建文件客户端 + * + * @param configId 配置编号 + * @param storage 存储器的枚举 {@link cn.iocoder.yudao.framework.file.core.enums.FileStorageEnum} + * @param config 文件配置 + */ + void createOrUpdateFileClient(Long configId, Integer storage, Config config); + +} diff --git a/yudao-framework/yudao-spring-boot-starter-file/src/main/java/cn/iocoder/yudao/framework/file/core/client/FileClientFactoryImpl.java b/yudao-framework/yudao-spring-boot-starter-file/src/main/java/cn/iocoder/yudao/framework/file/core/client/FileClientFactoryImpl.java new file mode 100644 index 0000000..8573cf1 --- /dev/null +++ b/yudao-framework/yudao-spring-boot-starter-file/src/main/java/cn/iocoder/yudao/framework/file/core/client/FileClientFactoryImpl.java @@ -0,0 +1,69 @@ +package cn.iocoder.yudao.framework.file.core.client; + +import cn.hutool.core.lang.Assert; +import cn.hutool.core.util.ReflectUtil; +import cn.iocoder.yudao.framework.file.core.enums.FileStorageEnum; +import lombok.extern.slf4j.Slf4j; + +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentMap; + +/** + * 文件客户端的工厂实现类 + * + * @author 芋道源码 + */ +@Slf4j +public class FileClientFactoryImpl implements FileClientFactory { + + /** + * 文件客户端 Map + * key:配置编号 + */ + private final ConcurrentMap> clients = new ConcurrentHashMap<>(); + + @Override + public FileClient getFileClient(Long channelId) { + AbstractFileClient client = clients.get(channelId); + if (client == null) { + log.error("[getFileClient][配置编号({}) 找不到客户端]", channelId); + } + return client; + } + + @Override + @SuppressWarnings("unchecked") + public void createOrUpdateFileClient(Long configId, Integer storage, Config config) { + AbstractFileClient client = (AbstractFileClient) clients.get(configId); + if (client == null) { + client = this.createFileClient(configId, storage, config); + client.init(); + clients.put(client.getId(), client); + } else { + client.refresh(config); + } + } + + @SuppressWarnings("unchecked") + private AbstractFileClient createFileClient( + Long configId, Integer storage, Config config) { + FileStorageEnum storageEnum = FileStorageEnum.getByStorage(storage); + Assert.notNull(storageEnum, String.format("文件配置(%s) 为空", storageEnum)); + // 创建客户端 +// switch (storageEnum) { +// case WX_PUB: return (AbstractFileClient) new WXPubFileClient(channelId, (WXFileClientConfig) config); +// case WX_LITE: return (AbstractFileClient) new WXPubFileClient(channelId, (WXFileClientConfig) config); +// case WX_APP: return (AbstractFileClient) new WXPubFileClient(channelId, (WXFileClientConfig) config); +// case ALIPAY_WAP: return (AbstractFileClient) new AlipayWapFileClient(channelId, (AlipayFileClientConfig) config); +// case ALIPAY_QR: return (AbstractFileClient) new AlipayQrFileClient(channelId, (AlipayFileClientConfig) config); +// case ALIPAY_APP: return (AbstractFileClient) new AlipayQrFileClient(channelId, (AlipayFileClientConfig) config); +// case ALIPAY_PC: return (AbstractFileClient) new AlipayQrFileClient(channelId, (AlipayFileClientConfig) config); +// } + return (AbstractFileClient) ReflectUtil.newInstance(storageEnum.getClientClass(), configId, config); +// storageEnum.getClientClass().newInstance() +// // 创建失败,错误日志 + 抛出异常 +// log.error("[createSmsClient][配置({}) 找不到合适的客户端实现]", config); +// throw new IllegalArgumentException(String.format("配置(%s) 找不到合适的客户端实现", config)); + } + +} diff --git a/yudao-framework/yudao-spring-boot-starter-file/src/main/java/cn/iocoder/yudao/framework/file/core/client/db/DBFileClient.java b/yudao-framework/yudao-spring-boot-starter-file/src/main/java/cn/iocoder/yudao/framework/file/core/client/db/DBFileClient.java new file mode 100644 index 0000000..57c649a --- /dev/null +++ b/yudao-framework/yudao-spring-boot-starter-file/src/main/java/cn/iocoder/yudao/framework/file/core/client/db/DBFileClient.java @@ -0,0 +1,41 @@ +package cn.iocoder.yudao.framework.file.core.client.db; + +import cn.hutool.extra.spring.SpringUtil; +import cn.iocoder.yudao.framework.file.core.client.AbstractFileClient; + +/** + * 基于 DB 存储的文件客户端的配置类 + * + * @author 芋道源码 + */ +public class DBFileClient extends AbstractFileClient { + + private DBFileContentFrameworkDAO dao; + + public DBFileClient(Long id, DBFileClientConfig config) { + super(id, config); + } + + @Override + protected void doInit() { + dao = SpringUtil.getBean(DBFileContentFrameworkDAO.class); + } + + @Override + public String upload(byte[] content, String path) { + dao.insert(getId(), path, content); + // 拼接返回路径 + return super.formatFileUrl(config.getDomain(), path); + } + + @Override + public void delete(String path) { + dao.delete(getId(), path); + } + + @Override + public byte[] getContent(String path) { + return dao.selectContent(getId(), path); + } + +} diff --git a/yudao-framework/yudao-spring-boot-starter-file/src/main/java/cn/iocoder/yudao/framework/file/core/client/db/DBFileClientConfig.java b/yudao-framework/yudao-spring-boot-starter-file/src/main/java/cn/iocoder/yudao/framework/file/core/client/db/DBFileClientConfig.java new file mode 100644 index 0000000..65d837b --- /dev/null +++ b/yudao-framework/yudao-spring-boot-starter-file/src/main/java/cn/iocoder/yudao/framework/file/core/client/db/DBFileClientConfig.java @@ -0,0 +1,24 @@ +package cn.iocoder.yudao.framework.file.core.client.db; + +import cn.iocoder.yudao.framework.file.core.client.FileClientConfig; +import lombok.Data; +import org.hibernate.validator.constraints.URL; + +import javax.validation.constraints.NotEmpty; + +/** + * 基于 DB 存储的文件客户端的配置类 + * + * @author 芋道源码 + */ +@Data +public class DBFileClientConfig implements FileClientConfig { + + /** + * 自定义域名 + */ + @NotEmpty(message = "domain 不能为空") + @URL(message = "domain 必须是 URL 格式") + private String domain; + +} diff --git a/yudao-framework/yudao-spring-boot-starter-file/src/main/java/cn/iocoder/yudao/framework/file/core/client/db/DBFileContentFrameworkDAO.java b/yudao-framework/yudao-spring-boot-starter-file/src/main/java/cn/iocoder/yudao/framework/file/core/client/db/DBFileContentFrameworkDAO.java new file mode 100644 index 0000000..44850ed --- /dev/null +++ b/yudao-framework/yudao-spring-boot-starter-file/src/main/java/cn/iocoder/yudao/framework/file/core/client/db/DBFileContentFrameworkDAO.java @@ -0,0 +1,16 @@ +package cn.iocoder.yudao.framework.file.core.client.db; + +/** + * 文件内容 Framework DAO 接口 + * + * @author 芋道源码 + */ +public interface DBFileContentFrameworkDAO { + + void insert(Long configId, String path, byte[] content); + + void delete(Long configId, String path); + + byte[] selectContent(Long configId, String path); + +} diff --git a/yudao-framework/yudao-spring-boot-starter-file/src/main/java/cn/iocoder/yudao/framework/file/core/client/ftp/FtpFileClient.java b/yudao-framework/yudao-spring-boot-starter-file/src/main/java/cn/iocoder/yudao/framework/file/core/client/ftp/FtpFileClient.java new file mode 100644 index 0000000..c02b469 --- /dev/null +++ b/yudao-framework/yudao-spring-boot-starter-file/src/main/java/cn/iocoder/yudao/framework/file/core/client/ftp/FtpFileClient.java @@ -0,0 +1,73 @@ +package cn.iocoder.yudao.framework.file.core.client.ftp; + +import cn.hutool.core.io.FileUtil; +import cn.hutool.core.util.CharsetUtil; +import cn.hutool.core.util.StrUtil; +import cn.hutool.extra.ftp.Ftp; +import cn.hutool.extra.ftp.FtpException; +import cn.hutool.extra.ftp.FtpMode; +import cn.iocoder.yudao.framework.file.core.client.AbstractFileClient; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.File; + +/** + * Ftp 文件客户端 + * + * @author 芋道源码 + */ +public class FtpFileClient extends AbstractFileClient { + + private Ftp ftp; + + public FtpFileClient(Long id, FtpFileClientConfig config) { + super(id, config); + } + + @Override + protected void doInit() { + // 补全风格。例如说 Linux 是 /,Windows 是 \ + if (!config.getBasePath().endsWith(File.separator)) { + config.setBasePath(config.getBasePath() + File.separator); + } + // 初始化 Ftp 对象 + this.ftp = new Ftp(config.getHost(), config.getPort(), config.getUsername(), config.getPassword(), + CharsetUtil.CHARSET_UTF_8, null, null, FtpMode.valueOf(config.getMode())); + } + + @Override + public String upload(byte[] content, String path) { + // 执行写入 + String filePath = getFilePath(path); + String fileName = FileUtil.getName(filePath); + String dir = StrUtil.removeSuffix(filePath, fileName); + boolean success = ftp.upload(dir, fileName, new ByteArrayInputStream(content)); + if (!success) { + throw new FtpException(StrUtil.format("上海文件到目标目录 ({}) 失败", filePath)); + } + // 拼接返回路径 + return super.formatFileUrl(config.getDomain(), path); + } + + @Override + public void delete(String path) { + String filePath = getFilePath(path); + ftp.delFile(filePath); + } + + @Override + public byte[] getContent(String path) { + String filePath = getFilePath(path); + String fileName = FileUtil.getName(filePath); + String dir = StrUtil.removeSuffix(path, fileName); + ByteArrayOutputStream out = new ByteArrayOutputStream(); + ftp.download(dir, fileName, out); + return out.toByteArray(); + } + + private String getFilePath(String path) { + return config.getBasePath() + path; + } + +} diff --git a/yudao-framework/yudao-spring-boot-starter-file/src/main/java/cn/iocoder/yudao/framework/file/core/client/ftp/FtpFileClientConfig.java b/yudao-framework/yudao-spring-boot-starter-file/src/main/java/cn/iocoder/yudao/framework/file/core/client/ftp/FtpFileClientConfig.java new file mode 100644 index 0000000..5ccf86c --- /dev/null +++ b/yudao-framework/yudao-spring-boot-starter-file/src/main/java/cn/iocoder/yudao/framework/file/core/client/ftp/FtpFileClientConfig.java @@ -0,0 +1,59 @@ +package cn.iocoder.yudao.framework.file.core.client.ftp; + +import cn.iocoder.yudao.framework.file.core.client.FileClientConfig; +import lombok.Data; +import org.hibernate.validator.constraints.URL; + +import javax.validation.constraints.NotEmpty; +import javax.validation.constraints.NotNull; + +/** + * Ftp 文件客户端的配置类 + * + * @author 芋道源码 + */ +@Data +public class FtpFileClientConfig implements FileClientConfig { + + /** + * 基础路径 + */ + @NotEmpty(message = "基础路径不能为空") + private String basePath; + + /** + * 自定义域名 + */ + @NotEmpty(message = "domain 不能为空") + @URL(message = "domain 必须是 URL 格式") + private String domain; + + /** + * 主机地址 + */ + @NotEmpty(message = "host 不能为空") + private String host; + /** + * 主机端口 + */ + @NotNull(message = "port 不能为空") + private Integer port; + /** + * 用户名 + */ + @NotEmpty(message = "用户名不能为空") + private String username; + /** + * 密码 + */ + @NotEmpty(message = "密码不能为空") + private String password; + /** + * 连接模式 + * + * 使用 {@link cn.hutool.extra.ftp.FtpMode} 对应的字符串 + */ + @NotEmpty(message = "连接模式不能为空") + private String mode; + +} diff --git a/yudao-framework/yudao-spring-boot-starter-file/src/main/java/cn/iocoder/yudao/framework/file/core/client/impl/AbstractFileClient.java b/yudao-framework/yudao-spring-boot-starter-file/src/main/java/cn/iocoder/yudao/framework/file/core/client/impl/AbstractFileClient.java deleted file mode 100644 index 4aef2f3..0000000 --- a/yudao-framework/yudao-spring-boot-starter-file/src/main/java/cn/iocoder/yudao/framework/file/core/client/impl/AbstractFileClient.java +++ /dev/null @@ -1,71 +0,0 @@ -package cn.iocoder.yudao.framework.file.core.client.impl; - -import cn.hutool.core.util.StrUtil; -import cn.iocoder.yudao.framework.file.core.client.FileClient; -import cn.iocoder.yudao.framework.file.core.client.FileClientConfig; -import lombok.extern.slf4j.Slf4j; - -/** - * 文件客户端的抽象类,提供模板方法,减少子类的冗余代码 - * - * @author 芋道源码 - */ -@Slf4j -public abstract class AbstractFileClient implements FileClient { - - /** - * 配置编号 - */ - private final Long id; - /** - * 文件配置 - */ - protected Config config; - - public AbstractFileClient(Long id, Config config) { - this.id = id; - this.config = config; - } - - /** - * 初始化 - */ - public final void init() { - doInit(); - log.info("[init][配置({}) 初始化完成]", config); - } - - /** - * 自定义初始化 - */ - protected abstract void doInit(); - - public final void refresh(Config config) { - // 判断是否更新 - if (config.equals(this.config)) { - return; - } - log.info("[refresh][配置({})发生变化,重新初始化]", config); - this.config = config; - // 初始化 - this.init(); - } - - @Override - public Long getId() { - return id; - } - - /** - * 格式化文件的 URL 访问地址 - * 使用场景:local、ftp、db,通过 FileController 的 getFile 来获取文件内容 - * - * @param domain 自定义域名 - * @param path 文件路径 - * @return URL 访问地址 - */ - protected String formatFileUrl(String domain, String path) { - return StrUtil.format("{}/system-api/{}/get/{}", domain, getId(), path); - } - -} diff --git a/yudao-framework/yudao-spring-boot-starter-file/src/main/java/cn/iocoder/yudao/framework/file/core/client/impl/ftp/FtpFileClient.java b/yudao-framework/yudao-spring-boot-starter-file/src/main/java/cn/iocoder/yudao/framework/file/core/client/impl/ftp/FtpFileClient.java deleted file mode 100644 index 556f4e2..0000000 --- a/yudao-framework/yudao-spring-boot-starter-file/src/main/java/cn/iocoder/yudao/framework/file/core/client/impl/ftp/FtpFileClient.java +++ /dev/null @@ -1,73 +0,0 @@ -package cn.iocoder.yudao.framework.file.core.client.impl.ftp; - -import cn.hutool.core.io.FileUtil; -import cn.hutool.core.util.CharsetUtil; -import cn.hutool.core.util.StrUtil; -import cn.hutool.extra.ftp.Ftp; -import cn.hutool.extra.ftp.FtpException; -import cn.hutool.extra.ftp.FtpMode; -import cn.iocoder.yudao.framework.file.core.client.impl.AbstractFileClient; - -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.File; - -/** - * Ftp 文件客户端 - * - * @author 芋道源码 - */ -public class FtpFileClient extends AbstractFileClient { - - private Ftp ftp; - - public FtpFileClient(Long id, FtpFileClientConfig config) { - super(id, config); - } - - @Override - protected void doInit() { - // 补全风格。例如说 Linux 是 /,Windows 是 \ - if (!config.getBasePath().endsWith(File.separator)) { - config.setBasePath(config.getBasePath() + File.separator); - } - // 初始化 Ftp 对象 - this.ftp = new Ftp(config.getHost(), config.getPort(), config.getUsername(), config.getPassword(), - CharsetUtil.CHARSET_UTF_8, null, null, FtpMode.valueOf(config.getMode())); - } - - @Override - public String upload(byte[] content, String path) { - // 执行写入 - String filePath = getFilePath(path); - String fileName = FileUtil.getName(filePath); - String dir = StrUtil.removeSuffix(filePath, fileName); - boolean success = ftp.upload(dir, fileName, new ByteArrayInputStream(content)); - if (!success) { - throw new FtpException(StrUtil.format("上海文件到目标目录 ({}) 失败", filePath)); - } - // 拼接返回路径 - return super.formatFileUrl(config.getDomain(), path); - } - - @Override - public void delete(String path) { - String filePath = getFilePath(path); - ftp.delFile(filePath); - } - - @Override - public byte[] getContent(String path) { - String filePath = getFilePath(path); - String fileName = FileUtil.getName(filePath); - String dir = StrUtil.removeSuffix(path, fileName); - ByteArrayOutputStream out = new ByteArrayOutputStream(); - ftp.download(dir, fileName, out); - return out.toByteArray(); - } - - private String getFilePath(String path) { - return config.getBasePath() + path; - } - -} diff --git a/yudao-framework/yudao-spring-boot-starter-file/src/main/java/cn/iocoder/yudao/framework/file/core/client/impl/ftp/FtpFileClientConfig.java b/yudao-framework/yudao-spring-boot-starter-file/src/main/java/cn/iocoder/yudao/framework/file/core/client/impl/ftp/FtpFileClientConfig.java deleted file mode 100644 index bc00382..0000000 --- a/yudao-framework/yudao-spring-boot-starter-file/src/main/java/cn/iocoder/yudao/framework/file/core/client/impl/ftp/FtpFileClientConfig.java +++ /dev/null @@ -1,59 +0,0 @@ -package cn.iocoder.yudao.framework.file.core.client.impl.ftp; - -import cn.iocoder.yudao.framework.file.core.client.FileClientConfig; -import lombok.Data; -import org.hibernate.validator.constraints.URL; - -import javax.validation.constraints.NotEmpty; -import javax.validation.constraints.NotNull; - -/** - * Ftp 文件客户端的配置类 - * - * @author 芋道源码 - */ -@Data -public class FtpFileClientConfig implements FileClientConfig { - - /** - * 基础路径 - */ - @NotEmpty(message = "基础路径不能为空") - private String basePath; - - /** - * 自定义域名 - */ - @NotEmpty(message = "domain 不能为空") - @URL(message = "domain 必须是 URL 格式") - private String domain; - - /** - * 主机地址 - */ - @NotEmpty(message = "host 不能为空") - private String host; - /** - * 主机端口 - */ - @NotNull(message = "port 不能为空") - private Integer port; - /** - * 用户名 - */ - @NotEmpty(message = "用户名不能为空") - private String username; - /** - * 密码 - */ - @NotEmpty(message = "密码不能为空") - private String password; - /** - * 连接模式 - * - * 使用 {@link cn.hutool.extra.ftp.FtpMode} 对应的字符串 - */ - @NotEmpty(message = "连接模式不能为空") - private String mode; - -} diff --git a/yudao-framework/yudao-spring-boot-starter-file/src/main/java/cn/iocoder/yudao/framework/file/core/client/impl/local/LocalFileClient.java b/yudao-framework/yudao-spring-boot-starter-file/src/main/java/cn/iocoder/yudao/framework/file/core/client/impl/local/LocalFileClient.java deleted file mode 100644 index aea6b1e..0000000 --- a/yudao-framework/yudao-spring-boot-starter-file/src/main/java/cn/iocoder/yudao/framework/file/core/client/impl/local/LocalFileClient.java +++ /dev/null @@ -1,52 +0,0 @@ -package cn.iocoder.yudao.framework.file.core.client.impl.local; - -import cn.hutool.core.io.FileUtil; -import cn.iocoder.yudao.framework.file.core.client.impl.AbstractFileClient; - -import java.io.File; - -/** - * 本地文件客户端 - * - * @author 芋道源码 - */ -public class LocalFileClient extends AbstractFileClient { - - public LocalFileClient(Long id, LocalFileClientConfig config) { - super(id, config); - } - - @Override - protected void doInit() { - // 补全风格。例如说 Linux 是 /,Windows 是 \ - if (!config.getBasePath().endsWith(File.separator)) { - config.setBasePath(config.getBasePath() + File.separator); - } - } - - @Override - public String upload(byte[] content, String path) { - // 执行写入 - String filePath = getFilePath(path); - FileUtil.writeBytes(content, filePath); - // 拼接返回路径 - return super.formatFileUrl(config.getDomain(), path); - } - - @Override - public void delete(String path) { - String filePath = getFilePath(path); - FileUtil.del(filePath); - } - - @Override - public byte[] getContent(String path) { - String filePath = getFilePath(path); - return FileUtil.readBytes(filePath); - } - - private String getFilePath(String path) { - return config.getBasePath() + path; - } - -} diff --git a/yudao-framework/yudao-spring-boot-starter-file/src/main/java/cn/iocoder/yudao/framework/file/core/client/impl/local/LocalFileClientConfig.java b/yudao-framework/yudao-spring-boot-starter-file/src/main/java/cn/iocoder/yudao/framework/file/core/client/impl/local/LocalFileClientConfig.java deleted file mode 100644 index 9820de7..0000000 --- a/yudao-framework/yudao-spring-boot-starter-file/src/main/java/cn/iocoder/yudao/framework/file/core/client/impl/local/LocalFileClientConfig.java +++ /dev/null @@ -1,30 +0,0 @@ -package cn.iocoder.yudao.framework.file.core.client.impl.local; - -import cn.iocoder.yudao.framework.file.core.client.FileClientConfig; -import lombok.Data; -import org.hibernate.validator.constraints.URL; - -import javax.validation.constraints.NotEmpty; - -/** - * 本地文件客户端的配置类 - * - * @author 芋道源码 - */ -@Data -public class LocalFileClientConfig implements FileClientConfig { - - /** - * 基础路径 - */ - @NotEmpty(message = "基础路径不能为空") - private String basePath; - - /** - * 自定义域名 - */ - @NotEmpty(message = "domain 不能为空") - @URL(message = "domain 必须是 URL 格式") - private String domain; - -} diff --git a/yudao-framework/yudao-spring-boot-starter-file/src/main/java/cn/iocoder/yudao/framework/file/core/client/impl/s3/S3FileClient.java b/yudao-framework/yudao-spring-boot-starter-file/src/main/java/cn/iocoder/yudao/framework/file/core/client/impl/s3/S3FileClient.java deleted file mode 100644 index 1f2b4aa..0000000 --- a/yudao-framework/yudao-spring-boot-starter-file/src/main/java/cn/iocoder/yudao/framework/file/core/client/impl/s3/S3FileClient.java +++ /dev/null @@ -1,103 +0,0 @@ -package cn.iocoder.yudao.framework.file.core.client.impl.s3; - -import cn.hutool.core.util.StrUtil; -import cn.iocoder.yudao.framework.file.core.client.impl.AbstractFileClient; -import software.amazon.awssdk.auth.credentials.AwsBasicCredentials; -import software.amazon.awssdk.auth.credentials.StaticCredentialsProvider; -import software.amazon.awssdk.core.sync.RequestBody; -import software.amazon.awssdk.regions.Region; -import software.amazon.awssdk.services.s3.S3Client; -import software.amazon.awssdk.services.s3.model.DeleteObjectRequest; -import software.amazon.awssdk.services.s3.model.GetObjectRequest; -import software.amazon.awssdk.services.s3.model.PutObjectRequest; - -import java.net.URI; - -import static cn.iocoder.yudao.framework.file.core.client.impl.s3.S3FileClientConfig.ENDPOINT_QINIU; - -/** - * 基于 S3 协议的文件客户端,实现 MinIO、阿里云、腾讯云、七牛云、华为云等云服务 - * - * S3 协议的客户端,采用亚马逊提供的 software.amazon.awssdk.s3 库 - * - * @author 芋道源码 - */ -public class S3FileClient extends AbstractFileClient { - - private S3Client client; - - public S3FileClient(Long id, S3FileClientConfig config) { - super(id, config); - } - - @Override - protected void doInit() { - // 补全 domain - if (StrUtil.isEmpty(config.getDomain())) { - config.setDomain(createDomain()); - } - // 初始化客户端 - client = S3Client.builder() - .serviceConfiguration(sb -> sb.pathStyleAccessEnabled(false) // 关闭路径风格 - .chunkedEncodingEnabled(false)) // 禁用 chunk - .endpointOverride(createURI()) // 上传地址 - .region(Region.of(config.getRegion())) // Region - .credentialsProvider(StaticCredentialsProvider.create( // 认证密钥 - AwsBasicCredentials.create(config.getAccessKey(), config.getAccessSecret()))) - .overrideConfiguration(cb -> cb.addExecutionInterceptor(new S3ModifyPathInterceptor(config.getBucket()))) - .build(); - } - - /** - * 基于 endpoint 构建调用云服务的 URI 地址 - * - * @return URI 地址 - */ - private URI createURI() { - String uri; - // 如果是七牛,无需拼接 bucket - if (config.getEndpoint().contains(ENDPOINT_QINIU)) { - uri = StrUtil.format("https://{}", config.getEndpoint()); - } else { - uri = StrUtil.format("https://{}.{}", config.getBucket(), config.getEndpoint()); - } - return URI.create(uri); - } - - /** - * 基于 bucket + endpoint 构建访问的 Domain 地址 - * - * @return Domain 地址 - */ - private String createDomain() { - return StrUtil.format("https://{}.{}", config.getBucket(), config.getEndpoint()); - } - - @Override - public String upload(byte[] content, String path) { - // 执行上传 - PutObjectRequest.Builder request = PutObjectRequest.builder() - .bucket(config.getBucket()) // bucket 必须传递 - .key(path); // 相对路径作为 key - client.putObject(request.build(), RequestBody.fromBytes(content)); - // 拼接返回路径 - return config.getDomain() + "/" + path; - } - - @Override - public void delete(String path) { - DeleteObjectRequest.Builder request = DeleteObjectRequest.builder() - .bucket(config.getBucket()) // bucket 必须传递 - .key(path); // 相对路径作为 key - client.deleteObject(request.build()); - } - - @Override - public byte[] getContent(String path) { - GetObjectRequest.Builder request = GetObjectRequest.builder() - .bucket(config.getBucket()) // bucket 必须传递 - .key(path); // 相对路径作为 key - return client.getObjectAsBytes(request.build()).asByteArray(); - } - -} diff --git a/yudao-framework/yudao-spring-boot-starter-file/src/main/java/cn/iocoder/yudao/framework/file/core/client/impl/s3/S3FileClientConfig.java b/yudao-framework/yudao-spring-boot-starter-file/src/main/java/cn/iocoder/yudao/framework/file/core/client/impl/s3/S3FileClientConfig.java deleted file mode 100644 index 858759c..0000000 --- a/yudao-framework/yudao-spring-boot-starter-file/src/main/java/cn/iocoder/yudao/framework/file/core/client/impl/s3/S3FileClientConfig.java +++ /dev/null @@ -1,83 +0,0 @@ -package cn.iocoder.yudao.framework.file.core.client.impl.s3; - -import cn.hutool.core.util.StrUtil; -import cn.iocoder.yudao.framework.file.core.client.FileClientConfig; -import lombok.Data; -import org.hibernate.validator.constraints.URL; - -import javax.validation.constraints.AssertTrue; -import javax.validation.constraints.NotNull; - -/** - * S3 文件客户端的配置类 - * - * @author 芋道源码 - */ -@Data -public class S3FileClientConfig implements FileClientConfig { - - public static final String ENDPOINT_QINIU = "qiniucs.com"; - - /** - * 节点地址 - * 1. MinIO: - * 2. 阿里云:https://help.aliyun.com/document_detail/31837.html - * 3. 腾讯云: - * 4. 七牛云:https://developer.qiniu.com/kodo/4088/s3-access-domainname - * 5. 华为云: - */ - @NotNull(message = "endpoint 不能为空") - private String endpoint; - /** - * 自定义域名 - * 1. MinIO: - * 2. 阿里云:https://help.aliyun.com/document_detail/31836.html - * 3. 腾讯云:https://cloud.tencent.com/document/product/436/11142 - * 4. 七牛云:https://developer.qiniu.com/kodo/8556/set-the-custom-source-domain-name - * 5. 华为云: - */ - @URL(message = "domain 必须是 URL 格式") - private String domain; - /** - * 区域 - * 1. MinIO: - * 2. 阿里云:https://help.aliyun.com/document_detail/31837.html - * 3. 腾讯云: - * 4. 七牛云:https://developer.qiniu.com/kodo/4088/s3-access-domainname - * 5. 华为云: - */ - @NotNull(message = "region 不能为空") - private String region; - /** - * 存储 Bucket - */ - @NotNull(message = "bucket 不能为空") - private String bucket; - - /** - * 访问 Key - * 1. MinIO: - * 2. 阿里云: - * 3. 腾讯云:https://console.cloud.tencent.com/cam/capi - * 4. 七牛云:https://portal.qiniu.com/user/key - * 5. 华为云: - */ - @NotNull(message = "accessKey 不能为空") - private String accessKey; - /** - * 访问 Secret - */ - @NotNull(message = "accessSecret 不能为空") - private String accessSecret; - - @AssertTrue(message = "domain 不能为空") - @SuppressWarnings("RedundantIfStatement") - public boolean isDomainValid() { - // 如果是七牛,必须带有 domain - if (endpoint.contains(ENDPOINT_QINIU) && StrUtil.isEmpty(domain)) { - return false; - } - return true; - } - -} diff --git a/yudao-framework/yudao-spring-boot-starter-file/src/main/java/cn/iocoder/yudao/framework/file/core/client/impl/s3/S3ModifyPathInterceptor.java b/yudao-framework/yudao-spring-boot-starter-file/src/main/java/cn/iocoder/yudao/framework/file/core/client/impl/s3/S3ModifyPathInterceptor.java deleted file mode 100644 index 2f4f19f..0000000 --- a/yudao-framework/yudao-spring-boot-starter-file/src/main/java/cn/iocoder/yudao/framework/file/core/client/impl/s3/S3ModifyPathInterceptor.java +++ /dev/null @@ -1,36 +0,0 @@ -package cn.iocoder.yudao.framework.file.core.client.impl.s3; - -import software.amazon.awssdk.core.interceptor.Context; -import software.amazon.awssdk.core.interceptor.ExecutionAttributes; -import software.amazon.awssdk.core.interceptor.ExecutionInterceptor; -import software.amazon.awssdk.http.SdkHttpRequest; - -/** - * S3 修改路径的拦截器,移除多余的 Bucket 前缀。 - * 如果不使用该拦截器,希望上传的路径是 /tudou.jpg 时,会被添加成 /bucket/tudou.jpg - * - * @author 芋道源码 - */ -public class S3ModifyPathInterceptor implements ExecutionInterceptor { - - private final String bucket; - - public S3ModifyPathInterceptor(String bucket) { - this.bucket = "/" + bucket; - } - - @Override - public SdkHttpRequest modifyHttpRequest(Context.ModifyHttpRequest context, ExecutionAttributes executionAttributes) { - SdkHttpRequest request = context.httpRequest(); - SdkHttpRequest.Builder rb = SdkHttpRequest.builder().protocol(request.protocol()).host(request.host()).port(request.port()) - .method(request.method()).headers(request.headers()).rawQueryParameters(request.rawQueryParameters()); - // 移除 path 前的 bucket 路径 - if (request.encodedPath().startsWith(bucket)) { - rb.encodedPath(request.encodedPath().substring(bucket.length())); - } else { - rb.encodedPath(request.encodedPath()); - } - return rb.build(); - } - -} diff --git a/yudao-framework/yudao-spring-boot-starter-file/src/main/java/cn/iocoder/yudao/framework/file/core/client/impl/sftp/SftpFileClient.java b/yudao-framework/yudao-spring-boot-starter-file/src/main/java/cn/iocoder/yudao/framework/file/core/client/impl/sftp/SftpFileClient.java deleted file mode 100644 index 7043002..0000000 --- a/yudao-framework/yudao-spring-boot-starter-file/src/main/java/cn/iocoder/yudao/framework/file/core/client/impl/sftp/SftpFileClient.java +++ /dev/null @@ -1,61 +0,0 @@ -package cn.iocoder.yudao.framework.file.core.client.impl.sftp; - -import cn.hutool.core.io.FileUtil; -import cn.hutool.extra.ssh.Sftp; -import cn.iocoder.yudao.framework.common.util.io.FileUtils; -import cn.iocoder.yudao.framework.file.core.client.impl.AbstractFileClient; - -import java.io.File; - -/** - * Sftp 文件客户端 - * - * @author 芋道源码 - */ -public class SftpFileClient extends AbstractFileClient { - - private Sftp sftp; - - public SftpFileClient(Long id, SftpFileClientConfig config) { - super(id, config); - } - - @Override - protected void doInit() { - // 补全风格。例如说 Linux 是 /,Windows 是 \ - if (!config.getBasePath().endsWith(File.separator)) { - config.setBasePath(config.getBasePath() + File.separator); - } - // 初始化 Ftp 对象 - this.sftp = new Sftp(config.getHost(), config.getPort(), config.getUsername(), config.getPassword()); - } - - @Override - public String upload(byte[] content, String path) { - // 执行写入 - String filePath = getFilePath(path); - File file = FileUtils.createTempFile(content); - sftp.upload(filePath, file); - // 拼接返回路径 - return super.formatFileUrl(config.getDomain(), path); - } - - @Override - public void delete(String path) { - String filePath = getFilePath(path); - sftp.delFile(filePath); - } - - @Override - public byte[] getContent(String path) { - String filePath = getFilePath(path); - File destFile = FileUtils.createTempFile(); - sftp.download(filePath, destFile); - return FileUtil.readBytes(destFile); - } - - private String getFilePath(String path) { - return config.getBasePath() + path; - } - -} diff --git a/yudao-framework/yudao-spring-boot-starter-file/src/main/java/cn/iocoder/yudao/framework/file/core/client/impl/sftp/SftpFileClientConfig.java b/yudao-framework/yudao-spring-boot-starter-file/src/main/java/cn/iocoder/yudao/framework/file/core/client/impl/sftp/SftpFileClientConfig.java deleted file mode 100644 index 6941e15..0000000 --- a/yudao-framework/yudao-spring-boot-starter-file/src/main/java/cn/iocoder/yudao/framework/file/core/client/impl/sftp/SftpFileClientConfig.java +++ /dev/null @@ -1,52 +0,0 @@ -package cn.iocoder.yudao.framework.file.core.client.impl.sftp; - -import cn.iocoder.yudao.framework.file.core.client.FileClientConfig; -import lombok.Data; -import org.hibernate.validator.constraints.URL; - -import javax.validation.constraints.NotEmpty; -import javax.validation.constraints.NotNull; - -/** - * Sftp 文件客户端的配置类 - * - * @author 芋道源码 - */ -@Data -public class SftpFileClientConfig implements FileClientConfig { - - /** - * 基础路径 - */ - @NotEmpty(message = "基础路径不能为空") - private String basePath; - - /** - * 自定义域名 - */ - @NotEmpty(message = "domain 不能为空") - @URL(message = "domain 必须是 URL 格式") - private String domain; - - /** - * 主机地址 - */ - @NotEmpty(message = "host 不能为空") - private String host; - /** - * 主机端口 - */ - @NotNull(message = "port 不能为空") - private Integer port; - /** - * 用户名 - */ - @NotEmpty(message = "用户名不能为空") - private String username; - /** - * 密码 - */ - @NotEmpty(message = "密码不能为空") - private String password; - -} diff --git a/yudao-framework/yudao-spring-boot-starter-file/src/main/java/cn/iocoder/yudao/framework/file/core/client/local/LocalFileClient.java b/yudao-framework/yudao-spring-boot-starter-file/src/main/java/cn/iocoder/yudao/framework/file/core/client/local/LocalFileClient.java new file mode 100644 index 0000000..1c79f89 --- /dev/null +++ b/yudao-framework/yudao-spring-boot-starter-file/src/main/java/cn/iocoder/yudao/framework/file/core/client/local/LocalFileClient.java @@ -0,0 +1,52 @@ +package cn.iocoder.yudao.framework.file.core.client.local; + +import cn.hutool.core.io.FileUtil; +import cn.iocoder.yudao.framework.file.core.client.AbstractFileClient; + +import java.io.File; + +/** + * 本地文件客户端 + * + * @author 芋道源码 + */ +public class LocalFileClient extends AbstractFileClient { + + public LocalFileClient(Long id, LocalFileClientConfig config) { + super(id, config); + } + + @Override + protected void doInit() { + // 补全风格。例如说 Linux 是 /,Windows 是 \ + if (!config.getBasePath().endsWith(File.separator)) { + config.setBasePath(config.getBasePath() + File.separator); + } + } + + @Override + public String upload(byte[] content, String path) { + // 执行写入 + String filePath = getFilePath(path); + FileUtil.writeBytes(content, filePath); + // 拼接返回路径 + return super.formatFileUrl(config.getDomain(), path); + } + + @Override + public void delete(String path) { + String filePath = getFilePath(path); + FileUtil.del(filePath); + } + + @Override + public byte[] getContent(String path) { + String filePath = getFilePath(path); + return FileUtil.readBytes(filePath); + } + + private String getFilePath(String path) { + return config.getBasePath() + path; + } + +} diff --git a/yudao-framework/yudao-spring-boot-starter-file/src/main/java/cn/iocoder/yudao/framework/file/core/client/local/LocalFileClientConfig.java b/yudao-framework/yudao-spring-boot-starter-file/src/main/java/cn/iocoder/yudao/framework/file/core/client/local/LocalFileClientConfig.java new file mode 100644 index 0000000..1f595ed --- /dev/null +++ b/yudao-framework/yudao-spring-boot-starter-file/src/main/java/cn/iocoder/yudao/framework/file/core/client/local/LocalFileClientConfig.java @@ -0,0 +1,30 @@ +package cn.iocoder.yudao.framework.file.core.client.local; + +import cn.iocoder.yudao.framework.file.core.client.FileClientConfig; +import lombok.Data; +import org.hibernate.validator.constraints.URL; + +import javax.validation.constraints.NotEmpty; + +/** + * 本地文件客户端的配置类 + * + * @author 芋道源码 + */ +@Data +public class LocalFileClientConfig implements FileClientConfig { + + /** + * 基础路径 + */ + @NotEmpty(message = "基础路径不能为空") + private String basePath; + + /** + * 自定义域名 + */ + @NotEmpty(message = "domain 不能为空") + @URL(message = "domain 必须是 URL 格式") + private String domain; + +} diff --git a/yudao-framework/yudao-spring-boot-starter-file/src/main/java/cn/iocoder/yudao/framework/file/core/client/s3/S3FileClient.java b/yudao-framework/yudao-spring-boot-starter-file/src/main/java/cn/iocoder/yudao/framework/file/core/client/s3/S3FileClient.java new file mode 100644 index 0000000..4fcc674 --- /dev/null +++ b/yudao-framework/yudao-spring-boot-starter-file/src/main/java/cn/iocoder/yudao/framework/file/core/client/s3/S3FileClient.java @@ -0,0 +1,103 @@ +package cn.iocoder.yudao.framework.file.core.client.s3; + +import cn.hutool.core.util.StrUtil; +import cn.iocoder.yudao.framework.file.core.client.AbstractFileClient; +import software.amazon.awssdk.auth.credentials.AwsBasicCredentials; +import software.amazon.awssdk.auth.credentials.StaticCredentialsProvider; +import software.amazon.awssdk.core.sync.RequestBody; +import software.amazon.awssdk.regions.Region; +import software.amazon.awssdk.services.s3.S3Client; +import software.amazon.awssdk.services.s3.model.DeleteObjectRequest; +import software.amazon.awssdk.services.s3.model.GetObjectRequest; +import software.amazon.awssdk.services.s3.model.PutObjectRequest; + +import java.net.URI; + +import static cn.iocoder.yudao.framework.file.core.client.s3.S3FileClientConfig.ENDPOINT_QINIU; + +/** + * 基于 S3 协议的文件客户端,实现 MinIO、阿里云、腾讯云、七牛云、华为云等云服务 + * + * S3 协议的客户端,采用亚马逊提供的 software.amazon.awssdk.s3 库 + * + * @author 芋道源码 + */ +public class S3FileClient extends AbstractFileClient { + + private S3Client client; + + public S3FileClient(Long id, S3FileClientConfig config) { + super(id, config); + } + + @Override + protected void doInit() { + // 补全 domain + if (StrUtil.isEmpty(config.getDomain())) { + config.setDomain(createDomain()); + } + // 初始化客户端 + client = S3Client.builder() + .serviceConfiguration(sb -> sb.pathStyleAccessEnabled(false) // 关闭路径风格 + .chunkedEncodingEnabled(false)) // 禁用 chunk + .endpointOverride(createURI()) // 上传地址 + .region(Region.of(config.getRegion())) // Region + .credentialsProvider(StaticCredentialsProvider.create( // 认证密钥 + AwsBasicCredentials.create(config.getAccessKey(), config.getAccessSecret()))) + .overrideConfiguration(cb -> cb.addExecutionInterceptor(new S3ModifyPathInterceptor(config.getBucket()))) + .build(); + } + + /** + * 基于 endpoint 构建调用云服务的 URI 地址 + * + * @return URI 地址 + */ + private URI createURI() { + String uri; + // 如果是七牛,无需拼接 bucket + if (config.getEndpoint().contains(ENDPOINT_QINIU)) { + uri = StrUtil.format("https://{}", config.getEndpoint()); + } else { + uri = StrUtil.format("https://{}.{}", config.getBucket(), config.getEndpoint()); + } + return URI.create(uri); + } + + /** + * 基于 bucket + endpoint 构建访问的 Domain 地址 + * + * @return Domain 地址 + */ + private String createDomain() { + return StrUtil.format("https://{}.{}", config.getBucket(), config.getEndpoint()); + } + + @Override + public String upload(byte[] content, String path) { + // 执行上传 + PutObjectRequest.Builder request = PutObjectRequest.builder() + .bucket(config.getBucket()) // bucket 必须传递 + .key(path); // 相对路径作为 key + client.putObject(request.build(), RequestBody.fromBytes(content)); + // 拼接返回路径 + return config.getDomain() + "/" + path; + } + + @Override + public void delete(String path) { + DeleteObjectRequest.Builder request = DeleteObjectRequest.builder() + .bucket(config.getBucket()) // bucket 必须传递 + .key(path); // 相对路径作为 key + client.deleteObject(request.build()); + } + + @Override + public byte[] getContent(String path) { + GetObjectRequest.Builder request = GetObjectRequest.builder() + .bucket(config.getBucket()) // bucket 必须传递 + .key(path); // 相对路径作为 key + return client.getObjectAsBytes(request.build()).asByteArray(); + } + +} diff --git a/yudao-framework/yudao-spring-boot-starter-file/src/main/java/cn/iocoder/yudao/framework/file/core/client/s3/S3FileClientConfig.java b/yudao-framework/yudao-spring-boot-starter-file/src/main/java/cn/iocoder/yudao/framework/file/core/client/s3/S3FileClientConfig.java new file mode 100644 index 0000000..3cb702d --- /dev/null +++ b/yudao-framework/yudao-spring-boot-starter-file/src/main/java/cn/iocoder/yudao/framework/file/core/client/s3/S3FileClientConfig.java @@ -0,0 +1,83 @@ +package cn.iocoder.yudao.framework.file.core.client.s3; + +import cn.hutool.core.util.StrUtil; +import cn.iocoder.yudao.framework.file.core.client.FileClientConfig; +import lombok.Data; +import org.hibernate.validator.constraints.URL; + +import javax.validation.constraints.AssertTrue; +import javax.validation.constraints.NotNull; + +/** + * S3 文件客户端的配置类 + * + * @author 芋道源码 + */ +@Data +public class S3FileClientConfig implements FileClientConfig { + + public static final String ENDPOINT_QINIU = "qiniucs.com"; + + /** + * 节点地址 + * 1. MinIO: + * 2. 阿里云:https://help.aliyun.com/document_detail/31837.html + * 3. 腾讯云: + * 4. 七牛云:https://developer.qiniu.com/kodo/4088/s3-access-domainname + * 5. 华为云: + */ + @NotNull(message = "endpoint 不能为空") + private String endpoint; + /** + * 自定义域名 + * 1. MinIO: + * 2. 阿里云:https://help.aliyun.com/document_detail/31836.html + * 3. 腾讯云:https://cloud.tencent.com/document/product/436/11142 + * 4. 七牛云:https://developer.qiniu.com/kodo/8556/set-the-custom-source-domain-name + * 5. 华为云: + */ + @URL(message = "domain 必须是 URL 格式") + private String domain; + /** + * 区域 + * 1. MinIO: + * 2. 阿里云:https://help.aliyun.com/document_detail/31837.html + * 3. 腾讯云: + * 4. 七牛云:https://developer.qiniu.com/kodo/4088/s3-access-domainname + * 5. 华为云: + */ + @NotNull(message = "region 不能为空") + private String region; + /** + * 存储 Bucket + */ + @NotNull(message = "bucket 不能为空") + private String bucket; + + /** + * 访问 Key + * 1. MinIO: + * 2. 阿里云: + * 3. 腾讯云:https://console.cloud.tencent.com/cam/capi + * 4. 七牛云:https://portal.qiniu.com/user/key + * 5. 华为云: + */ + @NotNull(message = "accessKey 不能为空") + private String accessKey; + /** + * 访问 Secret + */ + @NotNull(message = "accessSecret 不能为空") + private String accessSecret; + + @AssertTrue(message = "domain 不能为空") + @SuppressWarnings("RedundantIfStatement") + public boolean isDomainValid() { + // 如果是七牛,必须带有 domain + if (endpoint.contains(ENDPOINT_QINIU) && StrUtil.isEmpty(domain)) { + return false; + } + return true; + } + +} diff --git a/yudao-framework/yudao-spring-boot-starter-file/src/main/java/cn/iocoder/yudao/framework/file/core/client/s3/S3ModifyPathInterceptor.java b/yudao-framework/yudao-spring-boot-starter-file/src/main/java/cn/iocoder/yudao/framework/file/core/client/s3/S3ModifyPathInterceptor.java new file mode 100644 index 0000000..1b7550d --- /dev/null +++ b/yudao-framework/yudao-spring-boot-starter-file/src/main/java/cn/iocoder/yudao/framework/file/core/client/s3/S3ModifyPathInterceptor.java @@ -0,0 +1,36 @@ +package cn.iocoder.yudao.framework.file.core.client.s3; + +import software.amazon.awssdk.core.interceptor.Context; +import software.amazon.awssdk.core.interceptor.ExecutionAttributes; +import software.amazon.awssdk.core.interceptor.ExecutionInterceptor; +import software.amazon.awssdk.http.SdkHttpRequest; + +/** + * S3 修改路径的拦截器,移除多余的 Bucket 前缀。 + * 如果不使用该拦截器,希望上传的路径是 /tudou.jpg 时,会被添加成 /bucket/tudou.jpg + * + * @author 芋道源码 + */ +public class S3ModifyPathInterceptor implements ExecutionInterceptor { + + private final String bucket; + + public S3ModifyPathInterceptor(String bucket) { + this.bucket = "/" + bucket; + } + + @Override + public SdkHttpRequest modifyHttpRequest(Context.ModifyHttpRequest context, ExecutionAttributes executionAttributes) { + SdkHttpRequest request = context.httpRequest(); + SdkHttpRequest.Builder rb = SdkHttpRequest.builder().protocol(request.protocol()).host(request.host()).port(request.port()) + .method(request.method()).headers(request.headers()).rawQueryParameters(request.rawQueryParameters()); + // 移除 path 前的 bucket 路径 + if (request.encodedPath().startsWith(bucket)) { + rb.encodedPath(request.encodedPath().substring(bucket.length())); + } else { + rb.encodedPath(request.encodedPath()); + } + return rb.build(); + } + +} diff --git a/yudao-framework/yudao-spring-boot-starter-file/src/main/java/cn/iocoder/yudao/framework/file/core/client/sftp/SftpFileClient.java b/yudao-framework/yudao-spring-boot-starter-file/src/main/java/cn/iocoder/yudao/framework/file/core/client/sftp/SftpFileClient.java new file mode 100644 index 0000000..3e18e88 --- /dev/null +++ b/yudao-framework/yudao-spring-boot-starter-file/src/main/java/cn/iocoder/yudao/framework/file/core/client/sftp/SftpFileClient.java @@ -0,0 +1,61 @@ +package cn.iocoder.yudao.framework.file.core.client.sftp; + +import cn.hutool.core.io.FileUtil; +import cn.hutool.extra.ssh.Sftp; +import cn.iocoder.yudao.framework.common.util.io.FileUtils; +import cn.iocoder.yudao.framework.file.core.client.AbstractFileClient; + +import java.io.File; + +/** + * Sftp 文件客户端 + * + * @author 芋道源码 + */ +public class SftpFileClient extends AbstractFileClient { + + private Sftp sftp; + + public SftpFileClient(Long id, SftpFileClientConfig config) { + super(id, config); + } + + @Override + protected void doInit() { + // 补全风格。例如说 Linux 是 /,Windows 是 \ + if (!config.getBasePath().endsWith(File.separator)) { + config.setBasePath(config.getBasePath() + File.separator); + } + // 初始化 Ftp 对象 + this.sftp = new Sftp(config.getHost(), config.getPort(), config.getUsername(), config.getPassword()); + } + + @Override + public String upload(byte[] content, String path) { + // 执行写入 + String filePath = getFilePath(path); + File file = FileUtils.createTempFile(content); + sftp.upload(filePath, file); + // 拼接返回路径 + return super.formatFileUrl(config.getDomain(), path); + } + + @Override + public void delete(String path) { + String filePath = getFilePath(path); + sftp.delFile(filePath); + } + + @Override + public byte[] getContent(String path) { + String filePath = getFilePath(path); + File destFile = FileUtils.createTempFile(); + sftp.download(filePath, destFile); + return FileUtil.readBytes(destFile); + } + + private String getFilePath(String path) { + return config.getBasePath() + path; + } + +} diff --git a/yudao-framework/yudao-spring-boot-starter-file/src/main/java/cn/iocoder/yudao/framework/file/core/client/sftp/SftpFileClientConfig.java b/yudao-framework/yudao-spring-boot-starter-file/src/main/java/cn/iocoder/yudao/framework/file/core/client/sftp/SftpFileClientConfig.java new file mode 100644 index 0000000..1a976f5 --- /dev/null +++ b/yudao-framework/yudao-spring-boot-starter-file/src/main/java/cn/iocoder/yudao/framework/file/core/client/sftp/SftpFileClientConfig.java @@ -0,0 +1,52 @@ +package cn.iocoder.yudao.framework.file.core.client.sftp; + +import cn.iocoder.yudao.framework.file.core.client.FileClientConfig; +import lombok.Data; +import org.hibernate.validator.constraints.URL; + +import javax.validation.constraints.NotEmpty; +import javax.validation.constraints.NotNull; + +/** + * Sftp 文件客户端的配置类 + * + * @author 芋道源码 + */ +@Data +public class SftpFileClientConfig implements FileClientConfig { + + /** + * 基础路径 + */ + @NotEmpty(message = "基础路径不能为空") + private String basePath; + + /** + * 自定义域名 + */ + @NotEmpty(message = "domain 不能为空") + @URL(message = "domain 必须是 URL 格式") + private String domain; + + /** + * 主机地址 + */ + @NotEmpty(message = "host 不能为空") + private String host; + /** + * 主机端口 + */ + @NotNull(message = "port 不能为空") + private Integer port; + /** + * 用户名 + */ + @NotEmpty(message = "用户名不能为空") + private String username; + /** + * 密码 + */ + @NotEmpty(message = "密码不能为空") + private String password; + +} diff --git a/yudao-framework/yudao-spring-boot-starter-file/src/main/java/cn/iocoder/yudao/framework/file/core/enums/FileStorageEnum.java b/yudao-framework/yudao-spring-boot-starter-file/src/main/java/cn/iocoder/yudao/framework/file/core/enums/FileStorageEnum.java new file mode 100644 index 0000000..03c6ed8 --- /dev/null +++ b/yudao-framework/yudao-spring-boot-starter-file/src/main/java/cn/iocoder/yudao/framework/file/core/enums/FileStorageEnum.java @@ -0,0 +1,55 @@ +package cn.iocoder.yudao.framework.file.core.enums; + +import cn.hutool.core.util.ArrayUtil; +import cn.iocoder.yudao.framework.file.core.client.FileClient; +import cn.iocoder.yudao.framework.file.core.client.FileClientConfig; +import cn.iocoder.yudao.framework.file.core.client.db.DBFileClient; +import cn.iocoder.yudao.framework.file.core.client.db.DBFileClientConfig; +import cn.iocoder.yudao.framework.file.core.client.ftp.FtpFileClient; +import cn.iocoder.yudao.framework.file.core.client.ftp.FtpFileClientConfig; +import cn.iocoder.yudao.framework.file.core.client.local.LocalFileClient; +import cn.iocoder.yudao.framework.file.core.client.local.LocalFileClientConfig; +import cn.iocoder.yudao.framework.file.core.client.s3.S3FileClient; +import cn.iocoder.yudao.framework.file.core.client.s3.S3FileClientConfig; +import cn.iocoder.yudao.framework.file.core.client.sftp.SftpFileClient; +import cn.iocoder.yudao.framework.file.core.client.sftp.SftpFileClientConfig; +import lombok.AllArgsConstructor; +import lombok.Getter; + +/** + * 文件存储器枚举 + * + * @author 芋道源码 + */ +@AllArgsConstructor +@Getter +public enum FileStorageEnum { + + DB(1, DBFileClientConfig.class, DBFileClient.class), + + LOCAL(10, LocalFileClientConfig.class, LocalFileClient.class), + FTP(11, FtpFileClientConfig.class, FtpFileClient.class), + SFTP(12, SftpFileClientConfig.class, SftpFileClient.class), + + S3(20, S3FileClientConfig.class, S3FileClient.class), + ; + + /** + * 存储器 + */ + private final Integer storage; + + /** + * 配置类 + */ + private final Class configClass; + /** + * 客户端类 + */ + private final Class clientClass; + + public static FileStorageEnum getByStorage(Integer storage) { + return ArrayUtil.firstMatch(o -> o.getStorage().equals(storage), values()); + } + +} diff --git a/yudao-framework/yudao-spring-boot-starter-file/src/main/resources/META-INF/spring.factories b/yudao-framework/yudao-spring-boot-starter-file/src/main/resources/META-INF/spring.factories new file mode 100644 index 0000000..8d2a4be --- /dev/null +++ b/yudao-framework/yudao-spring-boot-starter-file/src/main/resources/META-INF/spring.factories @@ -0,0 +1,2 @@ +org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ + cn.iocoder.yudao.framework.file.config.YudaoFileAutoConfiguration diff --git a/yudao-framework/yudao-spring-boot-starter-file/src/test/java/cn/iocoder/yudao/framework/file/core/client/ftp/FtpFileClientTest.java b/yudao-framework/yudao-spring-boot-starter-file/src/test/java/cn/iocoder/yudao/framework/file/core/client/ftp/FtpFileClientTest.java index 7c37c01..ee0d740 100644 --- a/yudao-framework/yudao-spring-boot-starter-file/src/test/java/cn/iocoder/yudao/framework/file/core/client/ftp/FtpFileClientTest.java +++ b/yudao-framework/yudao-spring-boot-starter-file/src/test/java/cn/iocoder/yudao/framework/file/core/client/ftp/FtpFileClientTest.java @@ -3,8 +3,6 @@ package cn.iocoder.yudao.framework.file.core.client.ftp; import cn.hutool.core.io.resource.ResourceUtil; import cn.hutool.core.util.IdUtil; import cn.hutool.extra.ftp.FtpMode; -import cn.iocoder.yudao.framework.file.core.client.impl.ftp.FtpFileClient; -import cn.iocoder.yudao.framework.file.core.client.impl.ftp.FtpFileClientConfig; import org.junit.jupiter.api.Test; public class FtpFileClientTest { diff --git a/yudao-framework/yudao-spring-boot-starter-file/src/test/java/cn/iocoder/yudao/framework/file/core/client/local/LocalFileClientTest.java b/yudao-framework/yudao-spring-boot-starter-file/src/test/java/cn/iocoder/yudao/framework/file/core/client/local/LocalFileClientTest.java index 62e5ea2..60f781b 100644 --- a/yudao-framework/yudao-spring-boot-starter-file/src/test/java/cn/iocoder/yudao/framework/file/core/client/local/LocalFileClientTest.java +++ b/yudao-framework/yudao-spring-boot-starter-file/src/test/java/cn/iocoder/yudao/framework/file/core/client/local/LocalFileClientTest.java @@ -2,8 +2,6 @@ package cn.iocoder.yudao.framework.file.core.client.local; import cn.hutool.core.io.resource.ResourceUtil; import cn.hutool.core.util.IdUtil; -import cn.iocoder.yudao.framework.file.core.client.impl.local.LocalFileClient; -import cn.iocoder.yudao.framework.file.core.client.impl.local.LocalFileClientConfig; import org.junit.jupiter.api.Test; public class LocalFileClientTest { diff --git a/yudao-framework/yudao-spring-boot-starter-file/src/test/java/cn/iocoder/yudao/framework/file/core/client/package-info.java b/yudao-framework/yudao-spring-boot-starter-file/src/test/java/cn/iocoder/yudao/framework/file/core/client/package-info.java deleted file mode 100644 index b6c1cd4..0000000 --- a/yudao-framework/yudao-spring-boot-starter-file/src/test/java/cn/iocoder/yudao/framework/file/core/client/package-info.java +++ /dev/null @@ -1,4 +0,0 @@ -/** - * 占位,避免 package 无法提交到 Git 仓库 - */ -package cn.iocoder.yudao.framework.file.core.client; diff --git a/yudao-framework/yudao-spring-boot-starter-file/src/test/java/cn/iocoder/yudao/framework/file/core/client/s3/S3FileClientTest.java b/yudao-framework/yudao-spring-boot-starter-file/src/test/java/cn/iocoder/yudao/framework/file/core/client/s3/S3FileClientTest.java index 5d9224b..145894a 100644 --- a/yudao-framework/yudao-spring-boot-starter-file/src/test/java/cn/iocoder/yudao/framework/file/core/client/s3/S3FileClientTest.java +++ b/yudao-framework/yudao-spring-boot-starter-file/src/test/java/cn/iocoder/yudao/framework/file/core/client/s3/S3FileClientTest.java @@ -4,8 +4,6 @@ import cn.hutool.core.io.resource.ResourceUtil; import cn.hutool.core.util.IdUtil; import cn.hutool.core.util.StrUtil; import cn.iocoder.yudao.framework.common.util.validation.ValidationUtils; -import cn.iocoder.yudao.framework.file.core.client.impl.s3.S3FileClient; -import cn.iocoder.yudao.framework.file.core.client.impl.s3.S3FileClientConfig; import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; diff --git a/yudao-framework/yudao-spring-boot-starter-file/src/test/java/cn/iocoder/yudao/framework/file/core/client/sftp/SftpFileClientTest.java b/yudao-framework/yudao-spring-boot-starter-file/src/test/java/cn/iocoder/yudao/framework/file/core/client/sftp/SftpFileClientTest.java index 13e3310..cc8e59e 100644 --- a/yudao-framework/yudao-spring-boot-starter-file/src/test/java/cn/iocoder/yudao/framework/file/core/client/sftp/SftpFileClientTest.java +++ b/yudao-framework/yudao-spring-boot-starter-file/src/test/java/cn/iocoder/yudao/framework/file/core/client/sftp/SftpFileClientTest.java @@ -2,8 +2,6 @@ package cn.iocoder.yudao.framework.file.core.client.sftp; import cn.hutool.core.io.resource.ResourceUtil; import cn.hutool.core.util.IdUtil; -import cn.iocoder.yudao.framework.file.core.client.impl.sftp.SftpFileClient; -import cn.iocoder.yudao.framework.file.core.client.impl.sftp.SftpFileClientConfig; import org.junit.jupiter.api.Test; public class SftpFileClientTest { -- libgit2 0.21.4