From fb028d709135c6224f3e2e610c7916be52132087 Mon Sep 17 00:00:00 2001 From: duandazhi Date: Fri, 16 Jul 2021 18:50:33 +0800 Subject: [PATCH] =?UTF-8?q?1=E3=80=81=E5=A2=9E=E5=8A=A0qiniu=E4=BA=91?= =?UTF-8?q?=E5=AD=98=E5=82=A8=EF=BC=9B=202=EF=BC=9A=E9=87=8D=E6=9E=84confi?= =?UTF-8?q?g;=203:=20=E9=87=8D=E6=96=B0=E5=91=BD=E5=90=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ruoyi-modules/ruoyi-file/pom.xml | 8 + ...ication.java => RuoYiFileApplication.java} | 62 +++--- .../ruoyi/file/config/AliyunOssConfig.java | 52 +++-- .../com/ruoyi/file/config/CephConfig.java | 80 ++++++++ .../com/ruoyi/file/config/FastDfsConfig.java | 36 ++++ ...{ResourcesConfig.java => LocalConfig.java} | 111 ++++++---- .../ruoyi/file/config/QiniuKodoConfig.java | 73 +++++++ .../file/controller/SysFileController.java | 4 +- ...Impl.java => AliyunOssDsfServiceImpl.java} | 104 ++++------ ...rviceImpl.java => CephDfsServiceImpl.java} | 68 +++--- ...rviceImpl.java => FastDfsServiceImpl.java} | 153 +++++++------- ...erviceImpl.java => FtpDfsServiceImpl.java} | 7 +- ...{ISysFileService.java => IDfsService.java} | 193 +++++++++--------- ...viceImpl.java => LocalDfsServiceImpl.java} | 127 ++++++------ ...viceImpl.java => MinioDfsServiceImpl.java} | 180 ++++++++-------- .../file/service/QiniuDfsServiceImpl.java | 143 +++++++++++++ 16 files changed, 870 insertions(+), 531 deletions(-) rename ruoyi-modules/ruoyi-file/src/main/java/com/ruoyi/file/{RuoYFileApplication.java => RuoYiFileApplication.java} (89%) create mode 100644 ruoyi-modules/ruoyi-file/src/main/java/com/ruoyi/file/config/CephConfig.java create mode 100644 ruoyi-modules/ruoyi-file/src/main/java/com/ruoyi/file/config/FastDfsConfig.java rename ruoyi-modules/ruoyi-file/src/main/java/com/ruoyi/file/config/{ResourcesConfig.java => LocalConfig.java} (53%) create mode 100644 ruoyi-modules/ruoyi-file/src/main/java/com/ruoyi/file/config/QiniuKodoConfig.java rename ruoyi-modules/ruoyi-file/src/main/java/com/ruoyi/file/service/{AliyunOssFileServiceImpl.java => AliyunOssDsfServiceImpl.java} (85%) rename ruoyi-modules/ruoyi-file/src/main/java/com/ruoyi/file/service/{CephSysFileServiceImpl.java => CephDfsServiceImpl.java} (65%) rename ruoyi-modules/ruoyi-file/src/main/java/com/ruoyi/file/service/{FastDfsSysFileServiceImpl.java => FastDfsServiceImpl.java} (76%) rename ruoyi-modules/ruoyi-file/src/main/java/com/ruoyi/file/service/{FtpFileServiceImpl.java => FtpDfsServiceImpl.java} (91%) rename ruoyi-modules/ruoyi-file/src/main/java/com/ruoyi/file/service/{ISysFileService.java => IDfsService.java} (94%) rename ruoyi-modules/ruoyi-file/src/main/java/com/ruoyi/file/service/{LocalSysFileServiceImpl.java => LocalDfsServiceImpl.java} (56%) rename ruoyi-modules/ruoyi-file/src/main/java/com/ruoyi/file/service/{MinioSysFileServiceImpl.java => MinioDfsServiceImpl.java} (90%) create mode 100644 ruoyi-modules/ruoyi-file/src/main/java/com/ruoyi/file/service/QiniuDfsServiceImpl.java diff --git a/ruoyi-modules/ruoyi-file/pom.xml b/ruoyi-modules/ruoyi-file/pom.xml index 364fb611..fd9fe8c7 100644 --- a/ruoyi-modules/ruoyi-file/pom.xml +++ b/ruoyi-modules/ruoyi-file/pom.xml @@ -119,6 +119,14 @@ 1.11.415 + + + + com.qiniu + qiniu-java-sdk + [7.7.0, 7.7.99] + + diff --git a/ruoyi-modules/ruoyi-file/src/main/java/com/ruoyi/file/RuoYFileApplication.java b/ruoyi-modules/ruoyi-file/src/main/java/com/ruoyi/file/RuoYiFileApplication.java similarity index 89% rename from ruoyi-modules/ruoyi-file/src/main/java/com/ruoyi/file/RuoYFileApplication.java rename to ruoyi-modules/ruoyi-file/src/main/java/com/ruoyi/file/RuoYiFileApplication.java index 990dc1a4..1f320da9 100644 --- a/ruoyi-modules/ruoyi-file/src/main/java/com/ruoyi/file/RuoYFileApplication.java +++ b/ruoyi-modules/ruoyi-file/src/main/java/com/ruoyi/file/RuoYiFileApplication.java @@ -1,31 +1,31 @@ -package com.ruoyi.file; - -import org.springframework.boot.SpringApplication; -import org.springframework.boot.autoconfigure.SpringBootApplication; -import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration; -import com.ruoyi.common.swagger.annotation.EnableCustomSwagger2; - -/** - * 文件服务 - * - * @author ruoyi - */ -@EnableCustomSwagger2 -@SpringBootApplication(exclude = {DataSourceAutoConfiguration.class }) -public class RuoYFileApplication -{ - public static void main(String[] args) - { - SpringApplication.run(RuoYFileApplication.class, args); - System.out.println("(♥◠‿◠)ノ゙ 文件服务模块启动成功 ლ(´ڡ`ლ)゙ \n" + - " .-------. ____ __ \n" + - " | _ _ \\ \\ \\ / / \n" + - " | ( ' ) | \\ _. / ' \n" + - " |(_ o _) / _( )_ .' \n" + - " | (_,_).' __ ___(_ o _)' \n" + - " | |\\ \\ | || |(_,_)' \n" + - " | | \\ `' /| `-' / \n" + - " | | \\ / \\ / \n" + - " ''-' `'-' `-..-' "); - } -} +package com.ruoyi.file; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration; +import com.ruoyi.common.swagger.annotation.EnableCustomSwagger2; + +/** + * 文件服务 + * + * @author ruoyi + */ +@EnableCustomSwagger2 +@SpringBootApplication(exclude = {DataSourceAutoConfiguration.class }) +public class RuoYiFileApplication +{ + public static void main(String[] args) + { + SpringApplication.run(RuoYiFileApplication.class, args); + System.out.println("(♥◠‿◠)ノ゙ 文件服务模块启动成功 ლ(´ڡ`ლ)゙ \n" + + " .-------. ____ __ \n" + + " | _ _ \\ \\ \\ / / \n" + + " | ( ' ) | \\ _. / ' \n" + + " |(_ o _) / _( )_ .' \n" + + " | (_,_).' __ ___(_ o _)' \n" + + " | |\\ \\ | || |(_,_)' \n" + + " | | \\ `' /| `-' / \n" + + " | | \\ / \\ / \n" + + " ''-' `'-' `-..-' "); + } +} diff --git a/ruoyi-modules/ruoyi-file/src/main/java/com/ruoyi/file/config/AliyunOssConfig.java b/ruoyi-modules/ruoyi-file/src/main/java/com/ruoyi/file/config/AliyunOssConfig.java index 7e825a89..2f6447fb 100644 --- a/ruoyi-modules/ruoyi-file/src/main/java/com/ruoyi/file/config/AliyunOssConfig.java +++ b/ruoyi-modules/ruoyi-file/src/main/java/com/ruoyi/file/config/AliyunOssConfig.java @@ -1,5 +1,6 @@ package com.ruoyi.file.config; +import com.ruoyi.file.service.AliyunOssDsfServiceImpl; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.cloud.context.config.annotation.RefreshScope; import org.springframework.context.annotation.Configuration; @@ -8,10 +9,12 @@ import org.springframework.context.annotation.Configuration; * aliyun oss https://help.aliyun.com/learn/learningpath/oss.html ,需要购买 * * @author dazer + * + * @see AliyunOssDsfServiceImpl */ @RefreshScope @Configuration -@ConfigurationProperties(prefix = "aliyun.oss") +@ConfigurationProperties(prefix = "aliyunoss") public class AliyunOssConfig { /** * aliyun oss相关配置 @@ -20,11 +23,26 @@ public class AliyunOssConfig { * AccessKeySecret eg:ap8nmIvD1TctcCLsADS4JbkOoXOluW * BucketName eg:yuebaoxiao * Endpoint eg:oss-cn-shenzhen.aliyuncs.com + * + * ak 获取地址:https://ak-console.aliyun.com/#/accesskey + * + * 具体项目里面必须替换掉 + */ + private String accessKeyId = ""; + private String accessKeySecret = ""; + private String bucketName = ""; + private String endpoint = ""; + /** + * hostHttps: 是否开启了https, 需要在控制台配置 + * https://oss.console.aliyun.com/bucket/oss-cn-shanghai/hiber2019/domain + *

+ * 上传地址和访问地址经常是不一样的 + * 1、上传地址是内网;访问地址是外网; + * 2、上传地址是ip; 访问地址域名; + * 3、上传地址是http; 访问地址是https + * 4: eg: https://image.jl-media.cn */ - private String accessKeyId; - private String accessKeySecret; - private String ossBucketName; - private String ossEndpoint; + private String domain = null; public String getAccessKeyId() { return accessKeyId; @@ -42,19 +60,27 @@ public class AliyunOssConfig { this.accessKeySecret = accessKeySecret; } - public String getOssBucketName() { - return ossBucketName; + public String getBucketName() { + return bucketName; + } + + public void setBucketName(String bucketName) { + this.bucketName = bucketName; + } + + public String getEndpoint() { + return endpoint; } - public void setOssBucketName(String ossBucketName) { - this.ossBucketName = ossBucketName; + public void setEndpoint(String endpoint) { + this.endpoint = endpoint; } - public String getOssEndpoint() { - return ossEndpoint; + public String getDomain() { + return domain; } - public void setOssEndpoint(String ossEndpoint) { - this.ossEndpoint = ossEndpoint; + public void setDomain(String domain) { + this.domain = domain; } } diff --git a/ruoyi-modules/ruoyi-file/src/main/java/com/ruoyi/file/config/CephConfig.java b/ruoyi-modules/ruoyi-file/src/main/java/com/ruoyi/file/config/CephConfig.java new file mode 100644 index 00000000..03bef407 --- /dev/null +++ b/ruoyi-modules/ruoyi-file/src/main/java/com/ruoyi/file/config/CephConfig.java @@ -0,0 +1,80 @@ +package com.ruoyi.file.config; + +import com.ruoyi.file.service.CephDfsServiceImpl; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.cloud.context.config.annotation.RefreshScope; +import org.springframework.context.annotation.Configuration; + +/** + * @see CephDfsServiceImpl + * @author dazer + */ +@RefreshScope +@Configuration +@ConfigurationProperties( + prefix = "ceph" +) +public class CephConfig { + /** + * s3 提供的 accessKey secretKey + * 示例: + * AccessKey: XPVF8TESA1X4SFU***** + * SecretKey: hBBEFpV3qsyI7HAdCBzA2ZdAhuANJFRIUz**** + * BUCKET_NAME: 概念和阿里云 oss 一模一样 + * endpoint: 127.0.0.1 or oss-cn-shenzhen.aliyuncs.com + */ + private String accessKey = ""; + private String secretKey = ""; + private String endpoint = "127.0.0.1"; + private String bucketName = ""; + /** + * 访问地址,访问地址经常和上传地址不一样; + * 1:上传地址是内网; 访问地址外网; + * 2:上传地址ip; 访问地址域名; + * 3-1:eg: https://dfwwbook.oss-cn-zhangjiakou.aliyuncs.com/upload/product/20210625165727777_dzdpl.jpg + * 3-2:eg: https://dfwwbook.dfww.com.cn/upload/product/20210625165727777_dzdpl.jpg + * 4: 示例:domain: https://dfwwbook.dfww.com.cn + * 最后带不带斜杠都可以 + */ + private String domain = null; + + public String getAccessKey() { + return accessKey; + } + + public void setAccessKey(String accessKey) { + this.accessKey = accessKey; + } + + public String getSecretKey() { + return secretKey; + } + + public void setSecretKey(String secretKey) { + this.secretKey = secretKey; + } + + public String getEndpoint() { + return endpoint; + } + + public void setEndpoint(String endpoint) { + this.endpoint = endpoint; + } + + public String getBucketName() { + return bucketName; + } + + public void setBucketName(String bucketName) { + this.bucketName = bucketName; + } + + public String getDomain() { + return domain; + } + + public void setDomain(String domain) { + this.domain = domain; + } +} diff --git a/ruoyi-modules/ruoyi-file/src/main/java/com/ruoyi/file/config/FastDfsConfig.java b/ruoyi-modules/ruoyi-file/src/main/java/com/ruoyi/file/config/FastDfsConfig.java new file mode 100644 index 00000000..519198b7 --- /dev/null +++ b/ruoyi-modules/ruoyi-file/src/main/java/com/ruoyi/file/config/FastDfsConfig.java @@ -0,0 +1,36 @@ +package com.ruoyi.file.config; + +import com.github.tobato.fastdfs.FdfsClientConstants; +import com.github.tobato.fastdfs.domain.conn.PooledConnectionFactory; +import com.ruoyi.file.service.FastDfsServiceImpl; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.cloud.context.config.annotation.RefreshScope; +import org.springframework.context.annotation.Configuration; + +/** + * 阿里 fastdfs 配置 + * @author dazer + * @see FastDfsServiceImpl + * FastDFS配置 其他参数见:{@link PooledConnectionFactory} + */ +@RefreshScope +@Configuration +@ConfigurationProperties( + prefix = FdfsClientConstants.ROOT_CONFIG_PREFIX +) +public class FastDfsConfig extends PooledConnectionFactory { + /** + * 域名或本机访问地址 + * FastDFS配置 其他参数见:{@link PooledConnectionFactory} + * //@Value("${fdfs.domain}") + */ + public String domain; + + public String getDomain() { + return domain; + } + + public void setDomain(String domain) { + this.domain = domain; + } +} diff --git a/ruoyi-modules/ruoyi-file/src/main/java/com/ruoyi/file/config/ResourcesConfig.java b/ruoyi-modules/ruoyi-file/src/main/java/com/ruoyi/file/config/LocalConfig.java similarity index 53% rename from ruoyi-modules/ruoyi-file/src/main/java/com/ruoyi/file/config/ResourcesConfig.java rename to ruoyi-modules/ruoyi-file/src/main/java/com/ruoyi/file/config/LocalConfig.java index da97520c..77452170 100644 --- a/ruoyi-modules/ruoyi-file/src/main/java/com/ruoyi/file/config/ResourcesConfig.java +++ b/ruoyi-modules/ruoyi-file/src/main/java/com/ruoyi/file/config/LocalConfig.java @@ -1,40 +1,73 @@ -package com.ruoyi.file.config; - -import java.io.File; -import org.springframework.beans.factory.annotation.Value; -import org.springframework.cloud.context.config.annotation.RefreshScope; -import org.springframework.context.annotation.Configuration; -import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry; -import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; - -/** - * 通用映射配置 - * - * @author ruoyi - */ -@RefreshScope -@Configuration -public class ResourcesConfig implements WebMvcConfigurer -{ - /** - * 上传文件存储在本地的根路径 - * eg: D:/ruoyi/uploadPath - */ - @Value("${file.path}") - private String localFilePath; - - /** - * 资源映射路径 前缀 - * eg: /statics - */ - @Value("${file.prefix}") - public String localFilePrefix; - - @Override - public void addResourceHandlers(ResourceHandlerRegistry registry) - { - /** 本地文件上传路径 */ - registry.addResourceHandler(localFilePrefix + "/**") - .addResourceLocations("file:" + localFilePath + File.separator); - } +package com.ruoyi.file.config; + +import java.io.File; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.cloud.context.config.annotation.RefreshScope; +import org.springframework.context.annotation.Configuration; +import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry; +import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; + +/** + * 本地文件配置 + * 通用映射配置 + * + * @author ruoyi + */ +@RefreshScope +@Configuration +public class LocalConfig implements WebMvcConfigurer +{ + /** + * 资源映射路径 前缀 + * eg: eg: /statics + */ + @Value("${file.prefix}") + private String localFilePrefix; + + /** + * 域名或本机访问地址 + * eg: http://127.0.0.1:9300 + */ + @Value("${file.domain}") + private String domain; + + /** + * 上传文件存储在本地的根路径 + * eg: D:/ruoyi/uploadPath + */ + @Value("${file.path}") + private String localFilePath; + + @Override + public void addResourceHandlers(ResourceHandlerRegistry registry) + { + /** 本地文件上传路径 */ + registry.addResourceHandler(localFilePrefix + "/**") + .addResourceLocations("file:" + localFilePath + File.separator); + } + + public String getLocalFilePrefix() { + return localFilePrefix; + } + + public void setLocalFilePrefix(String localFilePrefix) { + this.localFilePrefix = localFilePrefix; + } + + public String getDomain() { + return domain; + } + + public void setDomain(String domain) { + this.domain = domain; + } + + public String getLocalFilePath() { + return localFilePath; + } + + public void setLocalFilePath(String localFilePath) { + this.localFilePath = localFilePath; + } } \ No newline at end of file diff --git a/ruoyi-modules/ruoyi-file/src/main/java/com/ruoyi/file/config/QiniuKodoConfig.java b/ruoyi-modules/ruoyi-file/src/main/java/com/ruoyi/file/config/QiniuKodoConfig.java new file mode 100644 index 00000000..8cbe372e --- /dev/null +++ b/ruoyi-modules/ruoyi-file/src/main/java/com/ruoyi/file/config/QiniuKodoConfig.java @@ -0,0 +1,73 @@ +package com.ruoyi.file.config; + +import com.qiniu.storage.Region; +import com.qiniu.storage.UploadManager; +import com.ruoyi.file.service.QiniuDfsServiceImpl; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.cloud.context.config.annotation.RefreshScope; +import org.springframework.context.annotation.Configuration; + +/** + * 七牛 文件存储产品叫做:kodo + * 对象存储:https://developer.qiniu.com/kodo/1239/java + * @author dazer + * @see UploadManager 上传核心类 + * @see Region 区域 or endpoint 【可选】 + * @see com.qiniu.storage.Configuration 配置类,可以配置 上传区域; 【可选】 + * @see QiniuDfsServiceImpl 实现 + */ +@RefreshScope +@Configuration +@ConfigurationProperties(prefix = "qiniu") +public class QiniuKodoConfig { + /** + * AccessKey 简称ak + * 申请地址=>登录七牛云:https://portal.qiniu.com/user/key + * ak 形如:pRYrSe_EW4sJHsQ6JyuiRYShA2JCLKtMhT-N4TQD + * =============================================== + * SecretKey 简称 sk + * 形如:CwTEh1kSLBdxBhIWfFz6h1GgDSokx97CYEV0cC1O + * =============================================== + * bucketName 获取地址:https://portal.qiniu.com/kodo/bucket + * =============================================== + * domain: 域名,一般都另外单独设置有一个访问的域名 + * =============================================== + * Region or endpoint: 七牛云会自动选择合适的 + */ + private String accessKey; + private String secretKey; + private String bucketName; + private String domain; + + public String getAccessKey() { + return accessKey; + } + + public void setAccessKey(String accessKey) { + this.accessKey = accessKey; + } + + public String getSecretKey() { + return secretKey; + } + + public void setSecretKey(String secretKey) { + this.secretKey = secretKey; + } + + public String getBucketName() { + return bucketName; + } + + public void setBucketName(String bucketName) { + this.bucketName = bucketName; + } + + public String getDomain() { + return domain; + } + + public void setDomain(String domain) { + this.domain = domain; + } +} diff --git a/ruoyi-modules/ruoyi-file/src/main/java/com/ruoyi/file/controller/SysFileController.java b/ruoyi-modules/ruoyi-file/src/main/java/com/ruoyi/file/controller/SysFileController.java index 318db416..435d9f46 100644 --- a/ruoyi-modules/ruoyi-file/src/main/java/com/ruoyi/file/controller/SysFileController.java +++ b/ruoyi-modules/ruoyi-file/src/main/java/com/ruoyi/file/controller/SysFileController.java @@ -1,5 +1,6 @@ package com.ruoyi.file.controller; +import com.ruoyi.file.service.IDfsService; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; @@ -8,7 +9,6 @@ import org.springframework.web.bind.annotation.RestController; import org.springframework.web.multipart.MultipartFile; import com.ruoyi.common.core.domain.R; import com.ruoyi.common.core.utils.file.FileUtils; -import com.ruoyi.file.service.ISysFileService; import com.ruoyi.system.api.domain.SysFile; /** @@ -22,7 +22,7 @@ public class SysFileController private static final Logger log = LoggerFactory.getLogger(SysFileController.class); @Autowired - private ISysFileService sysFileService; + private IDfsService sysFileService; /** * 文件上传请求 diff --git a/ruoyi-modules/ruoyi-file/src/main/java/com/ruoyi/file/service/AliyunOssFileServiceImpl.java b/ruoyi-modules/ruoyi-file/src/main/java/com/ruoyi/file/service/AliyunOssDsfServiceImpl.java similarity index 85% rename from ruoyi-modules/ruoyi-file/src/main/java/com/ruoyi/file/service/AliyunOssFileServiceImpl.java rename to ruoyi-modules/ruoyi-file/src/main/java/com/ruoyi/file/service/AliyunOssDsfServiceImpl.java index 7d935b96..dd69cf88 100644 --- a/ruoyi-modules/ruoyi-file/src/main/java/com/ruoyi/file/service/AliyunOssFileServiceImpl.java +++ b/ruoyi-modules/ruoyi-file/src/main/java/com/ruoyi/file/service/AliyunOssDsfServiceImpl.java @@ -12,7 +12,6 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.web.multipart.MultipartFile; -import javax.annotation.PostConstruct; import java.io.IOException; import java.io.InputStream; import java.math.BigDecimal; @@ -43,45 +42,10 @@ import java.util.concurrent.TimeUnit; * //@see AliyunMsgUtil */ @Service -public class AliyunOssFileServiceImpl implements ISysFileService { - private static final Logger log = LoggerFactory.getLogger(AliyunOssFileServiceImpl.class); +public class AliyunOssDsfServiceImpl implements IDfsService { + private static final Logger log = LoggerFactory.getLogger(AliyunOssDsfServiceImpl.class); @Autowired private AliyunOssConfig aliyunOssConfig; - /** - * 这些阿里云访问id - */ - private String ACCESS_KEY_ID; - private String ACCESS_KEY_SECRET; - private String BUCKET_NAME; - /** - * https://oss.console.aliyun.com/ - * 这些阿里云 oss 参数都需要替换 - *

- * 如果是内网的话,访问速度肯定更快,内网不限制速度。 - */ - private String ENDPOINT = "oss-cn-shenzhen.aliyuncs.com"; - private String ENDPOINT_INTERNAL = ENDPOINT.replace(".aliyuncs.com", "-internal.aliyuncs.com"); - - /** - * 域名绑定 - * USER_DOMAIN_NAME: 域名名称, oss 访问路径绑定的用户自定义域名; 如果没有,就设置为null - * hostHttps: 是否开启了https, 需要在控制台配置 - * https://oss.console.aliyun.com/bucket/oss-cn-shanghai/hiber2019/domain - *

- * private static final String USER_DOMAIN_NAME = "image.jl-media.cn"; - */ - private static final String USER_DOMAIN_NAME = null; - private static final boolean HOST_HTTPS = true; - - @PostConstruct - public void init() { - ACCESS_KEY_ID = aliyunOssConfig.getAccessKeyId(); - ACCESS_KEY_SECRET = aliyunOssConfig.getAccessKeySecret(); - BUCKET_NAME = aliyunOssConfig.getOssBucketName(); - ENDPOINT = aliyunOssConfig.getOssEndpoint(); - ENDPOINT_INTERNAL = ENDPOINT.replace(".aliyuncs.com", "-internal.aliyuncs.com"); - } - /** * demo 地址 https://help.aliyun.com/learn/learningpath/oss.html *

@@ -107,26 +71,31 @@ public class AliyunOssFileServiceImpl implements ISysFileService { requestKey = SpringUtil.getActiveProfile() + "/" + requestKey; } + /** + * https://oss.console.aliyun.com/ + * 这些阿里云 oss 参数都需要替换 + *

+ * 如果是内网的话,访问速度肯定更快,内网不限制速度。 + */ + String endpoint = aliyunOssConfig.getEndpoint(); + String endpointInternal = endpoint.replace(".aliyuncs.com", "-internal.aliyuncs.com"); + long mb5 = 5 * 1024 * 1024L; if (file.getSize() > mb5) { //大于5mb,我们就分片上传 - this.ossUploadFileBigMultiable(isProd ? ENDPOINT_INTERNAL : ENDPOINT, requestKey, file); + this.ossUploadFileBigMultiable(isProd ? endpointInternal : endpoint, requestKey, file); } else { //否则,我们常规上传 - this.ossUploadFileSmall(isProd ? ENDPOINT_INTERNAL : ENDPOINT, requestKey, file); + this.ossUploadFileSmall(isProd ? endpointInternal : endpoint, requestKey, file); } // 解析结果 // 注意,这里可能 需要 replace String accessPath; - if (StringUtils.isNotBlank(USER_DOMAIN_NAME)) { - if (HOST_HTTPS) { - accessPath = "https://" + USER_DOMAIN_NAME + "/" + requestKey; - } else { - accessPath = "http://" + USER_DOMAIN_NAME + "/" + requestKey; - } + if (StringUtils.isNotBlank(aliyunOssConfig.getDomain())) { + accessPath = aliyunOssConfig.getDomain() + "/" + requestKey; } else { - accessPath = "https://" + BUCKET_NAME + "." + ENDPOINT + "/" + requestKey; + accessPath = "https://" + aliyunOssConfig.getBucketName() + "." + aliyunOssConfig.getEndpoint() + "/" + requestKey; } return accessPath; } @@ -140,7 +109,7 @@ public class AliyunOssFileServiceImpl implements ISysFileService { /* * Constructs a client instance with your account for accessing OSS */ - OSS client = new OSSClientBuilder().build(ENDPOINT, ACCESS_KEY_ID, ACCESS_KEY_SECRET); + OSS client = new OSSClientBuilder().build(aliyunOssConfig.getEndpoint(), aliyunOssConfig.getAccessKeyId(), aliyunOssConfig.getAccessKeySecret()); String storePath = getStorePath(fileUrl); List keys = new ArrayList<>(); keys.add(storePath); @@ -151,7 +120,7 @@ public class AliyunOssFileServiceImpl implements ISysFileService { */ log.info("\nDeleting all objects:"); DeleteObjectsResult deleteObjectsResult = client.deleteObjects( - new DeleteObjectsRequest(BUCKET_NAME).withKeys(keys)); + new DeleteObjectsRequest(aliyunOssConfig.getBucketName()).withKeys(keys)); List deletedObjects = deleteObjectsResult.getDeletedObjects(); for (String object : deletedObjects) { log.info("\t" + object); @@ -185,10 +154,13 @@ public class AliyunOssFileServiceImpl implements ISysFileService { * @return upload/default/20190806202208849_jvs5g.png */ private String getStorePath(String filePath) { - String publicPath1 = "https://" + BUCKET_NAME + "." + ENDPOINT + "/"; - String publicPath2 = "http://" + BUCKET_NAME + "." + ENDPOINT + "/"; - String publicPath3 = "https://" + USER_DOMAIN_NAME + "/"; - String publicPath4 = "http://" + USER_DOMAIN_NAME + "/"; + String bucketName = aliyunOssConfig.getBucketName(); + String endPoint = aliyunOssConfig.getEndpoint(); + String domain = aliyunOssConfig.getDomain(); + String publicPath1 = "https://" + bucketName + "." + endPoint + "/"; + String publicPath2 = "http://" + bucketName + "." + endPoint + "/"; + String publicPath3 = "https://" + domain + "/"; + String publicPath4 = "http://" + domain + "/"; //String publicPath5 = ServletCacheUtils.getInstance().getHttpRootPath(); @@ -209,11 +181,11 @@ public class AliyunOssFileServiceImpl implements ISysFileService { * demo https://github.com/aliyun/aliyun-oss-java-sdk/blob/master/src/samples/UploadSample.java */ private String ossUploadFileSmall(String endpoint, String picturePath, MultipartFile file) throws IOException { - OSS ossClient = new OSSClientBuilder().build(endpoint, ACCESS_KEY_ID, ACCESS_KEY_SECRET); + OSS ossClient = new OSSClientBuilder().build(endpoint, aliyunOssConfig.getAccessKeyId(), aliyunOssConfig.getAccessKeySecret()); try { // 上传文件 (上传文件流的形式) - PutObjectResult putResult = ossClient.putObject(BUCKET_NAME, picturePath, file.getInputStream()); + PutObjectResult putResult = ossClient.putObject(aliyunOssConfig.getBucketName(), picturePath, file.getInputStream()); } catch (OSSException oe) { log.error("Caught an OSSException, which means your request made it to OSS, " + "but was rejected with an error response for some reason."); @@ -285,13 +257,13 @@ public class AliyunOssFileServiceImpl implements ISysFileService { */ ClientBuilderConfiguration conf = new ClientBuilderConfiguration(); conf.setIdleConnectionTime(1000); - OSS client = new OSSClientBuilder().build(endpoint, ACCESS_KEY_ID, ACCESS_KEY_SECRET, conf); + OSS client = new OSSClientBuilder().build(endpoint, aliyunOssConfig.getAccessKeyId(), aliyunOssConfig.getAccessKeySecret(), conf); try { /* * Claim a upload id firstly */ - InitiateMultipartUploadRequest request = new InitiateMultipartUploadRequest(BUCKET_NAME, requestKey); + InitiateMultipartUploadRequest request = new InitiateMultipartUploadRequest(aliyunOssConfig.getBucketName(), requestKey); InitiateMultipartUploadResult result = client.initiateMultipartUpload(request); String uploadId = result.getUploadId(); @@ -366,7 +338,7 @@ public class AliyunOssFileServiceImpl implements ISysFileService { if (log.isInfoEnabled()) { log.info("Fetching an object"); } - OSSObject ossObject = client.getObject(new GetObjectRequest(BUCKET_NAME, requestKey)); + OSSObject ossObject = client.getObject(new GetObjectRequest(aliyunOssConfig.getBucketName(), requestKey)); if (log.isInfoEnabled()) { log.info(ossObject.getKey()); } @@ -436,7 +408,7 @@ public class AliyunOssFileServiceImpl implements ISysFileService { instream.skip(this.startPos); UploadPartRequest uploadPartRequest = new UploadPartRequest(); - uploadPartRequest.setBucketName(BUCKET_NAME); + uploadPartRequest.setBucketName(aliyunOssConfig.getBucketName()); uploadPartRequest.setKey(this.requestKey); uploadPartRequest.setUploadId(this.uploadId); uploadPartRequest.setInputStream(instream); @@ -474,7 +446,7 @@ public class AliyunOssFileServiceImpl implements ISysFileService { } CompleteMultipartUploadRequest completeMultipartUploadRequest = - new CompleteMultipartUploadRequest(BUCKET_NAME, requestKey, uploadId, partETags); + new CompleteMultipartUploadRequest(aliyunOssConfig.getBucketName(), requestKey, uploadId, partETags); client.completeMultipartUpload(completeMultipartUploadRequest); } @@ -482,7 +454,7 @@ public class AliyunOssFileServiceImpl implements ISysFileService { if (log.isInfoEnabled()) { log.info("Listing all parts......"); } - ListPartsRequest listPartsRequest = new ListPartsRequest(BUCKET_NAME, requestKey, uploadId); + ListPartsRequest listPartsRequest = new ListPartsRequest(aliyunOssConfig.getBucketName(), requestKey, uploadId); PartListing partListing = client.listParts(listPartsRequest); int partCount = partListing.getParts().size(); @@ -498,8 +470,8 @@ public class AliyunOssFileServiceImpl implements ISysFileService { } @Override - public String listObject() { - OSS client = new OSSClientBuilder().build(ENDPOINT, ACCESS_KEY_ID, ACCESS_KEY_SECRET); + public String objectsCapacityStr() { + OSS client = new OSSClientBuilder().build(aliyunOssConfig.getEndpoint(), aliyunOssConfig.getAccessKeyId(), aliyunOssConfig.getAccessKeySecret()); final int maxKeys = 200; String nextMarker = null; ObjectListing objectListing; @@ -509,7 +481,7 @@ public class AliyunOssFileServiceImpl implements ISysFileService { do { - objectListing = client.listObjects(new ListObjectsRequest(BUCKET_NAME).withMarker(nextMarker).withMaxKeys(maxKeys)); + objectListing = client.listObjects(new ListObjectsRequest(aliyunOssConfig.getBucketName()).withMarker(nextMarker).withMaxKeys(maxKeys)); List sums = objectListing.getObjectSummaries(); for (OSSObjectSummary s : sums) { @@ -552,11 +524,11 @@ public class AliyunOssFileServiceImpl implements ISysFileService { } catch (MalformedURLException e) { // 忽略 } - OSS ossClient = new OSSClientBuilder().build(ENDPOINT, ACCESS_KEY_ID, ACCESS_KEY_SECRET); + OSS ossClient = new OSSClientBuilder().build(aliyunOssConfig.getEndpoint(), aliyunOssConfig.getAccessKeyId(), aliyunOssConfig.getAccessKeySecret()); // 设置URL过期时间为12小时,最大值就是43200 Date expiration = new Date(System.currentTimeMillis() + (43200 * 1000)); // 生成以GET方法访问的签名URL,访客可以直接通过浏览器访问相关内容。 - URL url = ossClient.generatePresignedUrl(BUCKET_NAME, objectName, expiration); + URL url = ossClient.generatePresignedUrl(aliyunOssConfig.getBucketName(), objectName, expiration); // 关闭OSSClient。 ossClient.shutdown(); return url.toString(); diff --git a/ruoyi-modules/ruoyi-file/src/main/java/com/ruoyi/file/service/CephSysFileServiceImpl.java b/ruoyi-modules/ruoyi-file/src/main/java/com/ruoyi/file/service/CephDfsServiceImpl.java similarity index 65% rename from ruoyi-modules/ruoyi-file/src/main/java/com/ruoyi/file/service/CephSysFileServiceImpl.java rename to ruoyi-modules/ruoyi-file/src/main/java/com/ruoyi/file/service/CephDfsServiceImpl.java index f83d4bcf..bf044995 100644 --- a/ruoyi-modules/ruoyi-file/src/main/java/com/ruoyi/file/service/CephSysFileServiceImpl.java +++ b/ruoyi-modules/ruoyi-file/src/main/java/com/ruoyi/file/service/CephDfsServiceImpl.java @@ -8,14 +8,16 @@ import com.amazonaws.auth.BasicAWSCredentials; import com.amazonaws.services.s3.AmazonS3; import com.amazonaws.services.s3.AmazonS3Client; import com.amazonaws.services.s3.model.*; -import com.ruoyi.common.core.utils.SpringUtils; -import com.ruoyi.file.utils.FileUploadUtils; +import com.ruoyi.common.core.exception.CustomException; +import com.ruoyi.file.config.CephConfig; import org.apache.commons.lang3.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; import org.springframework.web.multipart.MultipartFile; -import java.io.IOException; +import javax.annotation.PostConstruct; /** * @author dazer @@ -33,39 +35,25 @@ import java.io.IOException; * 2:ceph存储,使用docker部署 https://www.cnblogs.com/bladeyul/p/10649049.html * 3:使用docker 搭建 ceph 开发环境,使用aws sdk 存储数据 https://blog.csdn.net/freewebsys/article/details/79553386 */ -public class CephSysFileServiceImpl implements ISysFileService { - private static final Logger log = LoggerFactory.getLogger(AliyunOssFileServiceImpl.class); +@Service +public class CephDfsServiceImpl implements IDfsService { + private static final Logger log = LoggerFactory.getLogger(CephDfsServiceImpl.class); + @Autowired + private CephConfig cephConfig; protected static AmazonS3 amazonS3 = null; - /** - * s3 提供的 accessKey secretKey - * BUCKET_NAME: 概念和阿里云 oss 一模一样 - */ - private static String ACCESS_KEY = "XPVF8TESA1X4SFU*****"; - private static String SECRET_KEY = "hBBEFpV3qsyI7HAdCBzA2ZdAhuANJFRIUz****"; - private static String HOST = "127.0.0.1"; - private static String BUCKET_NAME = "dfwwbook"; - /** - * 域名绑定 - * USER_DOMAIN_NAME: 域名名称, oss 访问路径绑定的用户自定义域名; 如果没有,就设置为null - * hostHttps: 是否开启了https, 需要在控制台配置 - * https://oss.console.aliyun.com/bucket/oss-cn-shanghai/hiber2019/domain - *

- * private static final String USER_DOMAIN_NAME = "image.jl-media.cn"; - */ - private static final String USER_DOMAIN_NAME = null; - private static final boolean HOST_HTTPS = true; /** * ceph配置初始化 */ - static { + @PostConstruct + void init() { log.info("开始初始化ceph配置"); - AWSCredentials credentials = new BasicAWSCredentials(ACCESS_KEY, SECRET_KEY); + AWSCredentials credentials = new BasicAWSCredentials(cephConfig.getAccessKey(), cephConfig.getSecretKey()); ClientConfiguration clientConfiguration = new ClientConfiguration(); clientConfiguration.setProtocol(Protocol.HTTP); amazonS3 = new AmazonS3Client(credentials, clientConfiguration); - amazonS3.setEndpoint(HOST); + amazonS3.setEndpoint(cephConfig.getEndpoint()); log.info("ceph配置初始化成功"); } @@ -109,20 +97,16 @@ public class CephSysFileServiceImpl implements ISysFileService { // long mb5 = 5 * 1024 * 1024L; //大于5mb,我们就分片上传 - PutObjectResult result = amazonS3.putObject(BUCKET_NAME, requestKey, file.getInputStream(), new ObjectMetadata()); + PutObjectResult result = amazonS3.putObject(cephConfig.getBucketName(), requestKey, file.getInputStream(), new ObjectMetadata()); // 上传成功 if (result.isRequesterCharged()) { // 解析结果 // 注意,这里可能 需要 replace String accessPath; - if (StringUtils.isNotBlank(USER_DOMAIN_NAME)) { - if (HOST_HTTPS) { - accessPath = "https://" + USER_DOMAIN_NAME + "/" + requestKey; - } else { - accessPath = "http://" + USER_DOMAIN_NAME + "/" + requestKey; - } + if (StringUtils.isNotBlank(cephConfig.getDomain())) { + accessPath = cephConfig.getDomain() + "/" + requestKey; } else { - accessPath = "https://" + BUCKET_NAME + "/" + requestKey; + accessPath = "https://" + cephConfig.getBucketName() + "." + cephConfig.getEndpoint() + "/" + requestKey; } return accessPath; } @@ -135,13 +119,13 @@ public class CephSysFileServiceImpl implements ISysFileService { return false; } String storePath = getStorePath(fileUrl); - amazonS3.deleteObject(BUCKET_NAME, storePath); + amazonS3.deleteObject(cephConfig.getBucketName(), storePath); return true; } @Override - public String listObject() { - return null; + public String objectsCapacityStr() { + throw new CustomException("ceph-获取文件占用空间功能,敬请期待"); } /** @@ -151,17 +135,15 @@ public class CephSysFileServiceImpl implements ISysFileService { * @return upload/default/20190806202208849_jvs5g.png */ private String getStorePath(String filePath) { - String publicPath1 = "https://" + BUCKET_NAME + "/"; - String publicPath2 = "http://" + BUCKET_NAME + "/"; - String publicPath3 = "https://" + USER_DOMAIN_NAME + "/"; - String publicPath4 = "http://" + USER_DOMAIN_NAME + "/"; - //String publicPath5 = ServletCacheUtils.getInstance().getHttpRootPath(); + String publicPath1 = "https://" + cephConfig.getBucketName() + "/"; + String publicPath2 = "http://" + cephConfig.getBucketName() + "/"; + String publicPath3 = "https://" + cephConfig.getDomain() + "/"; + String publicPath4 = "http://" + cephConfig.getDomain() + "/"; filePath = filePath.replace(publicPath1, ""); filePath = filePath.replace(publicPath2, ""); filePath = filePath.replace(publicPath3, ""); filePath = filePath.replace(publicPath4, ""); - //filePath = filePath.replace(publicPath5, ""); return filePath; } } diff --git a/ruoyi-modules/ruoyi-file/src/main/java/com/ruoyi/file/service/FastDfsSysFileServiceImpl.java b/ruoyi-modules/ruoyi-file/src/main/java/com/ruoyi/file/service/FastDfsServiceImpl.java similarity index 76% rename from ruoyi-modules/ruoyi-file/src/main/java/com/ruoyi/file/service/FastDfsSysFileServiceImpl.java rename to ruoyi-modules/ruoyi-file/src/main/java/com/ruoyi/file/service/FastDfsServiceImpl.java index 76dbbe86..7f7af301 100644 --- a/ruoyi-modules/ruoyi-file/src/main/java/com/ruoyi/file/service/FastDfsSysFileServiceImpl.java +++ b/ruoyi-modules/ruoyi-file/src/main/java/com/ruoyi/file/service/FastDfsServiceImpl.java @@ -1,78 +1,75 @@ -package com.ruoyi.file.service; - -import com.github.tobato.fastdfs.domain.conn.PooledConnectionFactory; -import com.github.tobato.fastdfs.exception.FdfsUnsupportStorePathException; -import org.apache.commons.io.FilenameUtils; -import org.apache.commons.lang3.StringUtils; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.beans.factory.annotation.Value; -import org.springframework.stereotype.Service; -import org.springframework.web.multipart.MultipartFile; -import com.github.tobato.fastdfs.domain.fdfs.StorePath; -import com.github.tobato.fastdfs.service.FastFileStorageClient; - -/** - * FastDFS 文件存储 - * @author ruoyi - */ -@Service -public class FastDfsSysFileServiceImpl implements ISysFileService -{ - private final Logger logger = LoggerFactory.getLogger(FastDfsSysFileServiceImpl.class); - /** - * 域名或本机访问地址 - * FastDFS配置 其他参数见:{@link PooledConnectionFactory} - */ - @Value("${fdfs.domain}") - public String domain; - - @Autowired - private FastFileStorageClient storageClient; - - /** - * FastDfs文件上传接口 - * - * @param file 上传的文件 - * @return 访问地址 - * @throws Exception - */ - @Override - public String uploadFile(MultipartFile file) throws Exception - { - return this.uploadFile(file); - } - - @Override - public String uploadFile(MultipartFile file, String modules) throws Exception { - // fastdsf 这里的 modules 没用 - validateModule(file, modules); - - StorePath storePath = storageClient.uploadFile(file.getInputStream(), file.getSize(), - FilenameUtils.getExtension(file.getOriginalFilename()), null); - - /// fileUrl = "http://127.0.0.1:22122/" + storePath.getFullPath(); - return domain + "/" + storePath.getFullPath(); - } - - @Override - public boolean deleteFile(String fileUrl) { - if (StringUtils.isEmpty(fileUrl)) { - return false; - } - try { - StorePath storePath = StorePath.parseFromUrl(fileUrl); - storageClient.deleteFile(storePath.getGroup(), storePath.getPath()); - return true; - } catch (FdfsUnsupportStorePathException e) { - logger.warn(e.getMessage()); - } - return false; - } - - @Override - public String listObject() { - return null; - } -} +package com.ruoyi.file.service; + +import com.github.tobato.fastdfs.exception.FdfsUnsupportStorePathException; +import com.ruoyi.common.core.exception.CustomException; +import com.ruoyi.file.config.FastDfsConfig; +import org.apache.commons.io.FilenameUtils; +import org.apache.commons.lang3.StringUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.web.multipart.MultipartFile; +import com.github.tobato.fastdfs.domain.fdfs.StorePath; +import com.github.tobato.fastdfs.service.FastFileStorageClient; + +/** + * FastDFS 文件存储 + * @author ruoyi + * @see FastDfsConfig + */ +@Service +public class FastDfsServiceImpl implements IDfsService +{ + private final Logger logger = LoggerFactory.getLogger(FastDfsServiceImpl.class); + + @Autowired + private FastFileStorageClient storageClient; + @Autowired + private FastDfsConfig fastDfsConfig; + + /** + * FastDfs文件上传接口 + * + * @param file 上传的文件 + * @return 访问地址 + * @throws Exception + */ + @Override + public String uploadFile(MultipartFile file) throws Exception + { + return this.uploadFile(file); + } + + @Override + public String uploadFile(MultipartFile file, String modules) throws Exception { + // fastdsf 这里的 modules 没用 + validateModule(file, modules); + + StorePath storePath = storageClient.uploadFile(file.getInputStream(), file.getSize(), + FilenameUtils.getExtension(file.getOriginalFilename()), null); + + /// fileUrl = "http://127.0.0.1:22122/" + storePath.getFullPath(); + return fastDfsConfig.getDomain() + "/" + storePath.getFullPath(); + } + + @Override + public boolean deleteFile(String fileUrl) { + if (StringUtils.isEmpty(fileUrl)) { + return false; + } + try { + StorePath storePath = StorePath.parseFromUrl(fileUrl); + storageClient.deleteFile(storePath.getGroup(), storePath.getPath()); + return true; + } catch (FdfsUnsupportStorePathException e) { + logger.warn(e.getMessage()); + } + return false; + } + + @Override + public String objectsCapacityStr() { + throw new CustomException("fastdfs-获取文件占用空间功能,敬请期待"); + } +} diff --git a/ruoyi-modules/ruoyi-file/src/main/java/com/ruoyi/file/service/FtpFileServiceImpl.java b/ruoyi-modules/ruoyi-file/src/main/java/com/ruoyi/file/service/FtpDfsServiceImpl.java similarity index 91% rename from ruoyi-modules/ruoyi-file/src/main/java/com/ruoyi/file/service/FtpFileServiceImpl.java rename to ruoyi-modules/ruoyi-file/src/main/java/com/ruoyi/file/service/FtpDfsServiceImpl.java index 67123a69..8b09da33 100644 --- a/ruoyi-modules/ruoyi-file/src/main/java/com/ruoyi/file/service/FtpFileServiceImpl.java +++ b/ruoyi-modules/ruoyi-file/src/main/java/com/ruoyi/file/service/FtpDfsServiceImpl.java @@ -2,6 +2,7 @@ package com.ruoyi.file.service; import cn.hutool.extra.ftp.Ftp; import cn.hutool.extra.ftp.FtpMode; +import com.ruoyi.common.core.exception.CustomException; import com.ruoyi.file.config.FtpConfig; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; @@ -15,7 +16,7 @@ import java.io.IOException; * @author dazer */ @Service -public class FtpFileServiceImpl implements ISysFileService { +public class FtpDfsServiceImpl implements IDfsService { @Autowired private FtpConfig ftpConfig; public static final String ACCESS_PREFIX = ""; @@ -62,8 +63,8 @@ public class FtpFileServiceImpl implements ISysFileService { } @Override - public String listObject() { - return null; + public String objectsCapacityStr() { + throw new CustomException("fpt-获取文件占用空间功能,敬请期待"); } private String getStorePath(String filePath) { diff --git a/ruoyi-modules/ruoyi-file/src/main/java/com/ruoyi/file/service/ISysFileService.java b/ruoyi-modules/ruoyi-file/src/main/java/com/ruoyi/file/service/IDfsService.java similarity index 94% rename from ruoyi-modules/ruoyi-file/src/main/java/com/ruoyi/file/service/ISysFileService.java rename to ruoyi-modules/ruoyi-file/src/main/java/com/ruoyi/file/service/IDfsService.java index 26330a6e..edd6ec95 100644 --- a/ruoyi-modules/ruoyi-file/src/main/java/com/ruoyi/file/service/ISysFileService.java +++ b/ruoyi-modules/ruoyi-file/src/main/java/com/ruoyi/file/service/IDfsService.java @@ -1,97 +1,96 @@ -package com.ruoyi.file.service; - -import com.ruoyi.common.core.exception.file.FileNameLengthLimitExceededException; -import com.ruoyi.common.core.exception.file.InvalidExtensionException; -import com.ruoyi.common.core.utils.file.MimeTypeUtils; -import com.ruoyi.file.utils.FileUploadUtils; -import org.apache.commons.lang3.RandomStringUtils; -import org.apache.commons.lang3.StringUtils; -import org.springframework.web.multipart.MultipartFile; - -import java.io.IOException; -import java.util.Arrays; -import java.util.Objects; -import java.util.stream.Collectors; - -import static com.ruoyi.file.utils.FileUploadUtils.assertAllowed; -import static com.ruoyi.file.utils.FileUploadUtils.extractFilename; - -/** - * 文件上传接口 - * 1: default: 最原始的java文件上传 - * 2: ftp 使用ftp模拟文件服务器; 如:iis、linux ftp、vsftpd、FileZilla Server,需要自己搭建服务 - * 3: FastDfs 是淘宝开源的分布式文件系统; 淘宝 开发的分布式 dfs, 需要自己搭建服务 (FastDFS) - * 4: minio 轻量级分布式文件系统; 类似一个阿里云oss、腾讯COS的一个开源、轻量级别的对象存储付; - * 5: aliyun oss; aliyun oss https://help.aliyun.com/learn/learningpath/oss.html ,需要购买 - * 6: CEPH 分布式大数据文件存储系统 http://docs.ceph.org.cn/ - * @author ruoyi - */ -public interface ISysFileService -{ - /** - * 允许上传文件存放的目录 - * 不同项目,这里可能做不同的修改;不过不想区分,就default; - * 项目稍微大一些,如果不区分目录,后期要做删除 or 迁移就很麻烦; - */ - String[] DEFAULT_MODULES_NAME = { - // 图片 - "default", "banner", "product", "images", "music", - // pdf - "pdf" }; - - /** - * 文件上传接口 - * - * @param file 上传的文件 - * @return 访问地址 - * @throws Exception - */ - String uploadFile(MultipartFile file) throws Exception; - - String uploadFile(MultipartFile file, String modules) throws Exception; - - /** - * 删除文件 - * - * @param fileUrl 文件访问地址,全路径或者不是全路径都可以 - * @return - */ - boolean deleteFile(String fileUrl); - - /** - * 获取文件占用空间 - * 别名:objectsCapacity - * @return 文件大小字符串,eg: 100MB、2G - */ - String listObject(); - - /** - * 校验文件名称长度 & 校验文件大小 & 校验上传的目录是否是项目中注册了的 & 返回新的文件名称 - * - * @param file 文件 - * @param modules 模块,这里作为上传的文件夹使用;eg: 项目中有banner、video、music、txt、product、default 多个模块,不同模块存放到不同文件夹中; - * @return 新的系统生成的文件名称 - * @throws InvalidExtensionException - */ - default String validateModule(MultipartFile file, String modules) throws InvalidExtensionException { - Objects.requireNonNull(file, "文件不能为空!"); - modules = StringUtils.defaultString(modules, "default"); - - //1、这里校验上传文件的模块,如果没有注册,直接报错 - if (!Arrays.stream(DEFAULT_MODULES_NAME).collect(Collectors.toList()).contains(modules)) { - throw new RuntimeException("上传模块" + modules + "不存在,请现在 'FolderPath.UploadModules'中注册. 枚举值,请参见Home接口:api/getFolderPath"); - } - - // 2、校验文件名称长度 - /// String ext = (String.valueOf(file.getOriginalFilename()).substring(String.valueOf(file.getOriginalFilename()).lastIndexOf("."))).toLowerCase(); - int fileNamelength = file.getOriginalFilename().length(); - if (fileNamelength > FileUploadUtils.DEFAULT_FILE_NAME_LENGTH) - { - throw new FileNameLengthLimitExceededException(FileUploadUtils.DEFAULT_FILE_NAME_LENGTH); - } - - // 3、文件大小校验 - assertAllowed(file, MimeTypeUtils.DEFAULT_ALLOWED_EXTENSION); - return modules + "/" + extractFilename(file); - } -} +package com.ruoyi.file.service; + +import com.ruoyi.common.core.exception.file.FileNameLengthLimitExceededException; +import com.ruoyi.common.core.exception.file.InvalidExtensionException; +import com.ruoyi.common.core.utils.file.MimeTypeUtils; +import com.ruoyi.file.utils.FileUploadUtils; +import org.apache.commons.lang3.StringUtils; +import org.springframework.web.multipart.MultipartFile; + +import java.util.Arrays; +import java.util.Objects; +import java.util.stream.Collectors; + +import static com.ruoyi.file.utils.FileUploadUtils.assertAllowed; +import static com.ruoyi.file.utils.FileUploadUtils.extractFilename; + +/** + * 【DFS】 = Distributed file system 比 【Sys File】 名称要容易理解 + * 文件上传接口 + * 1: default: 最原始的java文件上传 + * 2: ftp 使用ftp模拟文件服务器; 如:iis、linux ftp、vsftpd、FileZilla Server,需要自己搭建服务 + * 3: FastDfs 是淘宝开源的分布式文件系统; 淘宝 开发的分布式 dfs, 需要自己搭建服务 (FastDFS) + * 4: minio 轻量级分布式文件系统; 类似一个阿里云oss、腾讯COS的一个开源、轻量级别的对象存储付; + * 5: aliyun oss; aliyun oss https://help.aliyun.com/learn/learningpath/oss.html ,需要购买 + * 6: CEPH 分布式大数据文件存储系统 http://docs.ceph.org.cn/ + * @author ruoyi + */ +public interface IDfsService +{ + /** + * 允许上传文件存放的目录 + * 不同项目,这里可能做不同的修改;不过不想区分,就default; + * 项目稍微大一些,如果不区分目录,后期要做删除 or 迁移就很麻烦; + */ + String[] DEFAULT_MODULES_NAME = { + // 图片 + "default", "banner", "product", "images", "music", + // pdf + "pdf" }; + + /** + * 文件上传接口 + * + * @param file 上传的文件 + * @return 访问地址 + * @throws Exception + */ + String uploadFile(MultipartFile file) throws Exception; + + String uploadFile(MultipartFile file, String modules) throws Exception; + + /** + * 删除文件 + * + * @param fileUrl 文件访问地址,全路径或者不是全路径都可以 + * @return + */ + boolean deleteFile(String fileUrl); + + /** + * 获取文件占用空间 + * 别名:objectsCapacity + * @return 文件大小字符串,eg: 100MB、2G + */ + String objectsCapacityStr(); + + /** + * 校验文件名称长度 & 校验文件大小 & 校验上传的目录是否是项目中注册了的 & 返回新的文件名称 + * + * @param file 文件 + * @param modules 模块,这里作为上传的文件夹使用;eg: 项目中有banner、video、music、txt、product、default 多个模块,不同模块存放到不同文件夹中; + * @return 新的系统生成的文件名称 + * @throws InvalidExtensionException + */ + default String validateModule(MultipartFile file, String modules) throws InvalidExtensionException { + Objects.requireNonNull(file, "文件不能为空!"); + modules = StringUtils.defaultString(modules, "default"); + + //1、这里校验上传文件的模块,如果没有注册,直接报错 + if (!Arrays.stream(DEFAULT_MODULES_NAME).collect(Collectors.toList()).contains(modules)) { + throw new RuntimeException("上传模块" + modules + "不存在,请现在 'FolderPath.UploadModules'中注册. 枚举值,请参见Home接口:api/getFolderPath"); + } + + // 2、校验文件名称长度 + /// String ext = (String.valueOf(file.getOriginalFilename()).substring(String.valueOf(file.getOriginalFilename()).lastIndexOf("."))).toLowerCase(); + int fileNamelength = file.getOriginalFilename().length(); + if (fileNamelength > FileUploadUtils.DEFAULT_FILE_NAME_LENGTH) + { + throw new FileNameLengthLimitExceededException(FileUploadUtils.DEFAULT_FILE_NAME_LENGTH); + } + + // 3、文件大小校验 + assertAllowed(file, MimeTypeUtils.DEFAULT_ALLOWED_EXTENSION); + return modules + "/" + extractFilename(file); + } +} diff --git a/ruoyi-modules/ruoyi-file/src/main/java/com/ruoyi/file/service/LocalSysFileServiceImpl.java b/ruoyi-modules/ruoyi-file/src/main/java/com/ruoyi/file/service/LocalDfsServiceImpl.java similarity index 56% rename from ruoyi-modules/ruoyi-file/src/main/java/com/ruoyi/file/service/LocalSysFileServiceImpl.java rename to ruoyi-modules/ruoyi-file/src/main/java/com/ruoyi/file/service/LocalDfsServiceImpl.java index 4414b14a..1655a0a8 100644 --- a/ruoyi-modules/ruoyi-file/src/main/java/com/ruoyi/file/service/LocalSysFileServiceImpl.java +++ b/ruoyi-modules/ruoyi-file/src/main/java/com/ruoyi/file/service/LocalDfsServiceImpl.java @@ -1,69 +1,58 @@ -package com.ruoyi.file.service; - -import org.apache.commons.lang3.StringUtils; -import org.springframework.beans.factory.annotation.Value; -import org.springframework.context.annotation.Primary; -import org.springframework.stereotype.Service; -import org.springframework.web.multipart.MultipartFile; -import com.ruoyi.file.utils.FileUploadUtils; - -/** - * 本地文件存储 - * - * @author ruoyi - */ -@Primary -@Service -public class LocalSysFileServiceImpl implements ISysFileService -{ - /** - * 资源映射路径 前缀 - * eg: eg: /statics - */ - @Value("${file.prefix}") - public String localFilePrefix; - - /** - * 域名或本机访问地址 - * eg: http://127.0.0.1:9300 - */ - @Value("${file.domain}") - public String domain; - - /** - * 上传文件存储在本地的根路径 - * eg: D:/ruoyi/uploadPath - */ - @Value("${file.path}") - private String localFilePath; - - /** - * 本地文件上传接口 - * - * @param file 上传的文件 - * @return 访问地址 - * @throws Exception - */ - @Override - public String uploadFile(MultipartFile file) throws Exception - { - return this.uploadFile(file, null); - } - - @Override - public String uploadFile(MultipartFile file, String modules) throws Exception { - String name = FileUploadUtils.upload(localFilePath + "/" + StringUtils.defaultString(modules, ""), file); - String url = domain + localFilePrefix + name; - return url; - } - - @Override - public boolean deleteFile(String fileUrl) { - return false; - } - - @Override - public String listObject() { - return null; - } -} +package com.ruoyi.file.service; + +import com.ruoyi.common.core.exception.CustomException; +import com.ruoyi.file.config.LocalConfig; +import org.apache.commons.lang3.StringUtils; +import org.springframework.context.annotation.Primary; +import org.springframework.stereotype.Service; +import org.springframework.web.multipart.MultipartFile; +import com.ruoyi.file.utils.FileUploadUtils; + +/** + * 本地文件存储 + * + * @author ruoyi + */ +@Primary +@Service +public class LocalDfsServiceImpl implements IDfsService +{ + private final LocalConfig localConfig; + + public LocalDfsServiceImpl(LocalConfig localConfig) { + this.localConfig = localConfig; + } + + /** + * 本地文件上传接口 + * + * @param file 上传的文件 + * @return 访问地址 + * @throws Exception + */ + @Override + public String uploadFile(MultipartFile file) throws Exception + { + return this.uploadFile(file, null); + } + + @Override + public String uploadFile(MultipartFile file, String modules) throws Exception { + String localFilePath = localConfig.getLocalFilePath(); + String domain = localConfig.getDomain(); + String localFilePrefix = localConfig.getLocalFilePrefix(); + + String name = FileUploadUtils.upload(localFilePath + "/" + StringUtils.defaultString(modules, ""), file); + return domain + localFilePrefix + name; + } + + @Override + public boolean deleteFile(String fileUrl) { + return false; + } + + @Override + public String objectsCapacityStr() { + throw new CustomException("本地存储-获取文件占用空间功能,敬请期待"); + } +} diff --git a/ruoyi-modules/ruoyi-file/src/main/java/com/ruoyi/file/service/MinioSysFileServiceImpl.java b/ruoyi-modules/ruoyi-file/src/main/java/com/ruoyi/file/service/MinioDfsServiceImpl.java similarity index 90% rename from ruoyi-modules/ruoyi-file/src/main/java/com/ruoyi/file/service/MinioSysFileServiceImpl.java rename to ruoyi-modules/ruoyi-file/src/main/java/com/ruoyi/file/service/MinioDfsServiceImpl.java index e1bd8c62..e0cd423d 100644 --- a/ruoyi-modules/ruoyi-file/src/main/java/com/ruoyi/file/service/MinioSysFileServiceImpl.java +++ b/ruoyi-modules/ruoyi-file/src/main/java/com/ruoyi/file/service/MinioDfsServiceImpl.java @@ -1,90 +1,90 @@ -package com.ruoyi.file.service; - -import cn.hutool.extra.spring.SpringUtil; -import io.minio.RemoveObjectArgs; -import io.minio.errors.*; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Service; -import org.springframework.web.multipart.MultipartFile; -import com.ruoyi.file.config.MinioConfig; -import com.ruoyi.file.utils.FileUploadUtils; -import io.minio.MinioClient; -import io.minio.PutObjectArgs; - -import java.io.IOException; -import java.security.InvalidKeyException; -import java.security.NoSuchAlgorithmException; - -/** - * Minio 文件存储 - * - * @author ruoyi - */ -@Service -public class MinioSysFileServiceImpl implements ISysFileService -{ - @Autowired - private MinioConfig minioConfig; - - @Autowired - private MinioClient client; - - /** - * 本地文件上传接口 - * - * @param file 上传的文件 - * @return 访问地址 - * @throws Exception - */ - @Override - public String uploadFile(MultipartFile file) throws Exception - { - return this.uploadFile(file, null); - } - - @Override - public String uploadFile(MultipartFile file, String modules) throws Exception { - String fileName = validateModule(file ,modules); - boolean isProd = "prod".equalsIgnoreCase(SpringUtil.getActiveProfile()); - if (!isProd) { - fileName = SpringUtil.getActiveProfile() + "/" + fileName; - } - - PutObjectArgs args = PutObjectArgs.builder() - .bucket(minioConfig.getBucketName()) - .object(fileName) - .stream(file.getInputStream(), file.getSize(), -1) - .contentType(file.getContentType()) - .build(); - client.putObject(args); - return minioConfig.getUrl() + "/" + minioConfig.getBucketName() + "/" + fileName; - } - - @Override - public boolean deleteFile(String fileUrl) { - RemoveObjectArgs args = RemoveObjectArgs.builder(). - bucket(minioConfig.getBucketName()). - object(fileUrl). - build(); - try { - client.removeObject(args); - return true; - } catch (ErrorResponseException | - InsufficientDataException | - InternalException | - InvalidKeyException | - InvalidResponseException | - IOException | - NoSuchAlgorithmException | - ServerException | - XmlParserException e) { - e.printStackTrace(); - } - return false; - } - - @Override - public String listObject() { - return null; - } -} +package com.ruoyi.file.service; + +import cn.hutool.extra.spring.SpringUtil; +import com.ruoyi.common.core.exception.CustomException; +import io.minio.RemoveObjectArgs; +import io.minio.errors.*; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.web.multipart.MultipartFile; +import com.ruoyi.file.config.MinioConfig; +import io.minio.MinioClient; +import io.minio.PutObjectArgs; + +import java.io.IOException; +import java.security.InvalidKeyException; +import java.security.NoSuchAlgorithmException; + +/** + * Minio 文件存储 + * + * @author ruoyi + */ +@Service +public class MinioDfsServiceImpl implements IDfsService +{ + @Autowired + private MinioConfig minioConfig; + + @Autowired + private MinioClient client; + + /** + * 本地文件上传接口 + * + * @param file 上传的文件 + * @return 访问地址 + * @throws Exception + */ + @Override + public String uploadFile(MultipartFile file) throws Exception + { + return this.uploadFile(file, null); + } + + @Override + public String uploadFile(MultipartFile file, String modules) throws Exception { + String fileName = validateModule(file ,modules); + boolean isProd = "prod".equalsIgnoreCase(SpringUtil.getActiveProfile()); + if (!isProd) { + fileName = SpringUtil.getActiveProfile() + "/" + fileName; + } + + PutObjectArgs args = PutObjectArgs.builder() + .bucket(minioConfig.getBucketName()) + .object(fileName) + .stream(file.getInputStream(), file.getSize(), -1) + .contentType(file.getContentType()) + .build(); + client.putObject(args); + return minioConfig.getUrl() + "/" + minioConfig.getBucketName() + "/" + fileName; + } + + @Override + public boolean deleteFile(String fileUrl) { + RemoveObjectArgs args = RemoveObjectArgs.builder(). + bucket(minioConfig.getBucketName()). + object(fileUrl). + build(); + try { + client.removeObject(args); + return true; + } catch (ErrorResponseException | + InsufficientDataException | + InternalException | + InvalidKeyException | + InvalidResponseException | + IOException | + NoSuchAlgorithmException | + ServerException | + XmlParserException e) { + e.printStackTrace(); + } + return false; + } + + @Override + public String objectsCapacityStr() { + throw new CustomException("minio存储-获取文件占用空间功能,敬请期待"); + } +} diff --git a/ruoyi-modules/ruoyi-file/src/main/java/com/ruoyi/file/service/QiniuDfsServiceImpl.java b/ruoyi-modules/ruoyi-file/src/main/java/com/ruoyi/file/service/QiniuDfsServiceImpl.java new file mode 100644 index 00000000..2843742a --- /dev/null +++ b/ruoyi-modules/ruoyi-file/src/main/java/com/ruoyi/file/service/QiniuDfsServiceImpl.java @@ -0,0 +1,143 @@ +package com.ruoyi.file.service; + +import cn.hutool.extra.spring.SpringUtil; +import com.alibaba.nacos.shaded.com.google.gson.Gson; +import com.qiniu.common.QiniuException; +import com.qiniu.http.Response; +import com.qiniu.storage.BucketManager; +import com.qiniu.storage.Configuration; +import com.qiniu.storage.Region; +import com.qiniu.storage.UploadManager; +import com.qiniu.storage.model.DefaultPutRet; +import com.qiniu.util.Auth; +import com.ruoyi.common.core.exception.CustomException; +import com.ruoyi.file.config.QiniuKodoConfig; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.web.multipart.MultipartFile; + +import java.io.InputStream; + +/** + * 七牛云 kodo 文件存储封装 + * + * @author dazer + * @see QiniuKodoConfig + * 参考:https://developer.qiniu.com/kodo/1239/java#upload-stream + * 路径:【对象存储==>JAVASDK==>文件上传==>数据流上传】 + */ +@Service +public class QiniuDfsServiceImpl implements IDfsService { + private static final Logger log = LoggerFactory.getLogger(QiniuDfsServiceImpl.class); + @Autowired + private QiniuKodoConfig qiniuKodoConfig; + + @Override + public String uploadFile(MultipartFile file) throws Exception { + return this.uploadFile(file, null); + } + + @Override + public String uploadFile(MultipartFile file, String modules) throws Exception { + //key: 这里不能以/开头 + String newName = validateModule(file, null); + //key: 这里不能以/开头 + String requestKey = "upload/" + "/" + newName; + //这里增加一个前缀区分一下是测试环境还是正式环境 + boolean isProd = "prod".equalsIgnoreCase(SpringUtil.getActiveProfile()); + if (!isProd) { + requestKey = SpringUtil.getActiveProfile() + "/" + requestKey; + } + + Configuration cfg = new Configuration(getCurrentRegion()); + //...其他参数参考类注释 + UploadManager uploadManager = new UploadManager(cfg); + + String accessKey = qiniuKodoConfig.getAccessKey(); + String secretKey = qiniuKodoConfig.getSecretKey(); + String bucket = qiniuKodoConfig.getBucketName(); + //默认不指定key的情况下,以文件内容的hash值作为文件名 + String key = requestKey; + + InputStream byteInputStream = file.getInputStream(); + Auth auth = Auth.create(accessKey, secretKey); + String upToken = auth.uploadToken(bucket); + try { + Response response = uploadManager.put(byteInputStream, key, upToken, null, null); + //解析上传成功的结果 + DefaultPutRet putRet = new Gson().fromJson(response.bodyString(), DefaultPutRet.class); + System.out.println(putRet.key); + System.out.println(putRet.hash); + } catch (QiniuException ex) { + Response r = ex.response; + String json = null; + try { + json = r.bodyString(); + } catch (QiniuException e) { + log.error(e.getMessage()); + } + log.error("【七牛云】-上传文件- 失败,原因1:" + r); + log.error("【七牛云】-上传文件-失败,原因2:" + json); + } + return null; + } + + @Override + public boolean deleteFile(String fileUrl) { + Configuration cfg = new Configuration(getCurrentRegion()); + + //...其他参数参考类注释 + String accessKey = qiniuKodoConfig.getAccessKey(); + String secretKey = qiniuKodoConfig.getSecretKey(); + String bucket = qiniuKodoConfig.getBucketName(); + Auth auth = Auth.create(accessKey, secretKey); + BucketManager bucketManager = new BucketManager(auth, cfg); + + String key = getStorePath(fileUrl); + try { + bucketManager.delete(bucket, key); + } catch (QiniuException ex) { + //如果遇到异常,说明删除失败 + log.error("【七牛云】-删除文件-失败 code:" + ex.code() + "=>" + ex.response.toString()); + } + return false; + } + + @Override + public String objectsCapacityStr() { + throw new CustomException("七牛云-获取文件占用空间功能,敬请期待"); + } + + /** + * 转换url + * + * @param filePath http://guangdong-oss.ityun.ltd/upload/default/header.jpg + * @return upload/default/header.jpg + * + * http://qwc2geifw.hn-bkt.clouddn.com/upload/default/header.jpg + * ==> upload/default/header.jpg + */ + private String getStorePath(String filePath) { + String domain = qiniuKodoConfig.getDomain(); + String publicPath3 = domain + "/"; + filePath = filePath.replace(publicPath3, ""); + return filePath; + } + + /** + * 存储区域 https://developer.qiniu.com/kodo/1671/region-endpoint-fq + * new Region.Builder() + * https://developer.qiniu.com/kodo/1239/java#upload-stream + * 自定义区域域名: 搜索【其中关于Region对象和机房的关系如下:】 + * @return 存储区域 + */ + private Region getCurrentRegion() { + /// 其中关于Region对象和机房的关系如下: + ///Region region = Region.autoRegion(); + ///Region region = Region.region0(); + //构造一个带指定 Region 对象的配置类 + return Region.huadong(); + } +}