From a0d68be942b10d16da8d95f31bc11173fce39d8a Mon Sep 17 00:00:00 2001 From: duandazhi Date: Sun, 18 Jul 2021 14:51:59 +0800 Subject: [PATCH] =?UTF-8?q?=E4=B8=83=E7=89=9B=E4=BA=91=E6=96=87=E4=BB=B6?= =?UTF-8?q?=E5=AD=98=E5=82=A8=E6=B5=8B=E8=AF=95=E5=AE=8C=E6=AF=95=E3=80=81?= =?UTF-8?q?minio=E6=96=87=E4=BB=B6=E5=AD=98=E5=82=A8=E6=B5=8B=E8=AF=95?= =?UTF-8?q?=E5=AE=8C=E6=AF=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/ruoyi/file/config/MinioConfig.java | 14 +++++++ .../file/service/AliyunOssDsfServiceImpl.java | 6 +-- .../file/service/CephDfsServiceImpl.java | 5 ++- .../file/service/FtpFileServiceImpl.java | 3 +- .../com/ruoyi/file/service/IDfsService.java | 28 +++++++++++-- .../file/service/MinioDfsServiceImpl.java | 42 +++++++++++++++++-- .../file/service/QiniuDfsServiceImpl.java | 17 +++++--- .../src/main/resources/bootstrap.yml | 11 ++++- 8 files changed, 105 insertions(+), 21 deletions(-) diff --git a/ruoyi-modules/ruoyi-file/src/main/java/com/ruoyi/file/config/MinioConfig.java b/ruoyi-modules/ruoyi-file/src/main/java/com/ruoyi/file/config/MinioConfig.java index 31b6d67f..c0e89be3 100644 --- a/ruoyi-modules/ruoyi-file/src/main/java/com/ruoyi/file/config/MinioConfig.java +++ b/ruoyi-modules/ruoyi-file/src/main/java/com/ruoyi/file/config/MinioConfig.java @@ -44,6 +44,12 @@ public class MinioConfig { */ private String bucketName; + /** + * 访问域名; url经常是内网地址,外部访问用域名或者外网ip + * eg: https://image.bj.gov.cn/appt-file + */ + private String domain; + public String getUrl() { return url; } @@ -76,6 +82,14 @@ public class MinioConfig { this.bucketName = bucketName; } + public String getDomain() { + return domain; + } + + public void setDomain(String domain) { + this.domain = domain; + } + @Bean public MinioClient getMinioClient() { return MinioClient.builder().endpoint(url).credentials(accessKey, secretKey).build(); diff --git a/ruoyi-modules/ruoyi-file/src/main/java/com/ruoyi/file/service/AliyunOssDsfServiceImpl.java b/ruoyi-modules/ruoyi-file/src/main/java/com/ruoyi/file/service/AliyunOssDsfServiceImpl.java index 7756a782..b9429499 100644 --- a/ruoyi-modules/ruoyi-file/src/main/java/com/ruoyi/file/service/AliyunOssDsfServiceImpl.java +++ b/ruoyi-modules/ruoyi-file/src/main/java/com/ruoyi/file/service/AliyunOssDsfServiceImpl.java @@ -42,7 +42,6 @@ import java.util.concurrent.TimeUnit; * @date 2019/8/6 19:02 * //@see AliyunMsgUtil */ -@Primary @Service public class AliyunOssDsfServiceImpl implements IDfsService { private static final Logger log = LoggerFactory.getLogger(AliyunOssDsfServiceImpl.class); @@ -64,7 +63,8 @@ public class AliyunOssDsfServiceImpl implements IDfsService { @Override public String uploadFile(MultipartFile file, String modules) throws Exception { //key: 这里不能以/开头 - String newName = validateModule(file, null); + validateModule(file, null); + String newName = extractFileNameSimple(file); //key: 这里不能以/开头 String requestKey = "upload/" + StringUtils.defaultString(modules, "default") + "/" + newName; //这里增加一个前缀区分一下是测试环境还是正式环境 @@ -153,7 +153,7 @@ public class AliyunOssDsfServiceImpl implements IDfsService { * 转换url * * @param filePath https://hiber2019.oss-cn-shanghai.aliyuncs.com/upload/default/20190806202208849_jvs5g.png - * eg2: 上传之后的格式:https://react-yuebaoxiao-pro.oss-cn-shanghai.aliyuncs.com/dev//upload/default/20210717-a77f6bb0-7b0a-4ef1-a839-f8e8aca469b8.jpeg + * eg2: 上传之后的格式:https://react-yuebaoxiao-pro.oss-cn-shanghai.aliyuncs.com/dev/upload/default/20210717-a77f6bb0-7b0a-4ef1-a839-f8e8aca469b8.jpeg * @return upload/default/20190806202208849_jvs5g.png */ private String getStorePath(String filePath) { diff --git a/ruoyi-modules/ruoyi-file/src/main/java/com/ruoyi/file/service/CephDfsServiceImpl.java b/ruoyi-modules/ruoyi-file/src/main/java/com/ruoyi/file/service/CephDfsServiceImpl.java index bf044995..ff410e88 100644 --- a/ruoyi-modules/ruoyi-file/src/main/java/com/ruoyi/file/service/CephDfsServiceImpl.java +++ b/ruoyi-modules/ruoyi-file/src/main/java/com/ruoyi/file/service/CephDfsServiceImpl.java @@ -86,9 +86,10 @@ public class CephDfsServiceImpl implements IDfsService { @Override public String uploadFile(MultipartFile file, String modules) throws Exception { //key: 这里不能以/开头 - String newName = validateModule(file, null); + validateModule(file, modules); + String newName = extractFileNameSimple(file); //key: 这里不能以/开头 - String requestKey = "upload/" + newName; + String requestKey = "upload/" + StringUtils.defaultString(modules, "default") + "/" + newName; //这里增加一个前缀区分一下是测试环境还是正式环境 boolean isProd = "prod".equalsIgnoreCase(SpringUtil.getActiveProfile()); if (!isProd) { 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/FtpFileServiceImpl.java index 8f035e5c..14f7c077 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/FtpFileServiceImpl.java @@ -29,7 +29,8 @@ public class FtpFileServiceImpl implements IDfsService { @Override public String uploadFile(MultipartFile file, String modules) throws Exception { - String fileName = validateModule(file, modules); + validateModule(file, modules); + String fileName = extractFileNameSimple(file); modules = StringUtils.defaultString(modules, "default"); String picturePath = "/upload/" + modules; diff --git a/ruoyi-modules/ruoyi-file/src/main/java/com/ruoyi/file/service/IDfsService.java b/ruoyi-modules/ruoyi-file/src/main/java/com/ruoyi/file/service/IDfsService.java index 31041825..4440fbf8 100644 --- a/ruoyi-modules/ruoyi-file/src/main/java/com/ruoyi/file/service/IDfsService.java +++ b/ruoyi-modules/ruoyi-file/src/main/java/com/ruoyi/file/service/IDfsService.java @@ -2,6 +2,8 @@ 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.DateUtils; +import com.ruoyi.common.core.utils.IdUtils; import com.ruoyi.common.core.utils.file.MimeTypeUtils; import com.ruoyi.file.utils.FileUploadUtils; import org.apache.commons.lang3.StringUtils; @@ -11,8 +13,7 @@ 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; +import static com.ruoyi.file.utils.FileUploadUtils.*; /** * 【DFS】 = Distributed file system 比 【Sys File】 名称要容易理解 @@ -71,7 +72,7 @@ public interface IDfsService * @param modules 模块,这里作为上传的文件夹使用;eg: 项目中有banner、video、music、txt、product、default 多个模块,不同模块存放到不同文件夹中; * @return 新的系统生成的文件名称 */ - default String validateModule(MultipartFile file, String modules) throws InvalidExtensionException { + default void validateModule(MultipartFile file, String modules) throws InvalidExtensionException { Objects.requireNonNull(file, "文件不能为空!"); modules = StringUtils.defaultString(modules, "default"); @@ -90,6 +91,25 @@ public interface IDfsService // 3、文件大小校验 assertAllowed(file, MimeTypeUtils.DEFAULT_ALLOWED_EXTENSION); - return extractFilename(file); + } + + /** + * @return 获取文件名称,简化版本,不包含斜杠 /; 形如:/20210717-a77f6bb0-7b0a-4ef1-a839-f8e8aca469b8.jpeg + */ + default String extractFileNameSimple(MultipartFile file) { + String fileName = file.getOriginalFilename(); + String extension = getExtension(file); + fileName = DateUtils.dateTime() + "-" + IdUtils.fastUUID() + "." + extension; + return fileName; + } + + /** + * @return 获取文件名称,包含斜杠 /; 形如:/2021/07/17/a77f6bb0-7b0a-4ef1-a839-f8e8aca469b8.jpeg + */ + default String extractFileName(MultipartFile file) { + String fileName = file.getOriginalFilename(); + String extension = getExtension(file); + fileName = DateUtils.datePath() + "/" + IdUtils.fastUUID() + "." + extension; + return fileName; } } diff --git a/ruoyi-modules/ruoyi-file/src/main/java/com/ruoyi/file/service/MinioDfsServiceImpl.java b/ruoyi-modules/ruoyi-file/src/main/java/com/ruoyi/file/service/MinioDfsServiceImpl.java index e0cd423d..4f8b742f 100644 --- a/ruoyi-modules/ruoyi-file/src/main/java/com/ruoyi/file/service/MinioDfsServiceImpl.java +++ b/ruoyi-modules/ruoyi-file/src/main/java/com/ruoyi/file/service/MinioDfsServiceImpl.java @@ -4,7 +4,9 @@ import cn.hutool.extra.spring.SpringUtil; import com.ruoyi.common.core.exception.CustomException; import io.minio.RemoveObjectArgs; import io.minio.errors.*; +import org.apache.commons.lang3.StringUtils; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Primary; import org.springframework.stereotype.Service; import org.springframework.web.multipart.MultipartFile; import com.ruoyi.file.config.MinioConfig; @@ -19,13 +21,22 @@ import java.security.NoSuchAlgorithmException; * Minio 文件存储 * * @author ruoyi + * 官网博客: http://docs.minio.org.cn/docs/master/java-client-quickstart-guidec + * 在springboot中使用Minio8 https://springboot.io/t/topic/3109 + * 1、上传操作:putObject + * 2、删除操作:removeObject + * ================== + * 3、预签(Presigned)操作:【设置访问过期时间】:【支持对url进行鉴权:【sts】【临时授权】】presignedGetObject + * presignedGetObject(String bucketName, String objectName, Integer expires) + * http://docs.minio.org.cn/docs/master/java-client-api-reference#presignedGetObject + * MinIO STS快速入门指南 http://docs.minio.org.cn/docs/master/minio-sts-quickstart-guide */ +@Primary @Service public class MinioDfsServiceImpl implements IDfsService { @Autowired private MinioConfig minioConfig; - @Autowired private MinioClient client; @@ -44,7 +55,8 @@ public class MinioDfsServiceImpl implements IDfsService @Override public String uploadFile(MultipartFile file, String modules) throws Exception { - String fileName = validateModule(file ,modules); + validateModule(file ,modules); + String fileName = StringUtils.defaultString(modules, "default") + "/" + extractFileName(file); boolean isProd = "prod".equalsIgnoreCase(SpringUtil.getActiveProfile()); if (!isProd) { fileName = SpringUtil.getActiveProfile() + "/" + fileName; @@ -57,14 +69,16 @@ public class MinioDfsServiceImpl implements IDfsService .contentType(file.getContentType()) .build(); client.putObject(args); - return minioConfig.getUrl() + "/" + minioConfig.getBucketName() + "/" + fileName; + //return minioConfig.getUrl() + "/" + minioConfig.getBucketName() + "/" + fileName; + //形如:https://image.bj.gov.cn/appt-file/dev/default/2021/07/18/f4243eb2-06a1-4304-bdfc-e2964b8721bb.jpeg + return minioConfig.getDomain() + "/" + minioConfig.getBucketName() + "/" + fileName; } @Override public boolean deleteFile(String fileUrl) { RemoveObjectArgs args = RemoveObjectArgs.builder(). bucket(minioConfig.getBucketName()). - object(fileUrl). + object(getStorePath(fileUrl)). build(); try { client.removeObject(args); @@ -87,4 +101,24 @@ public class MinioDfsServiceImpl implements IDfsService public String objectsCapacityStr() { throw new CustomException("minio存储-获取文件占用空间功能,敬请期待"); } + + /** + * 转换url,为原始的key + * + * @param filePath https://image.bj.gov.cn/appt-file/dev/default/2021/07/18/f4243eb2-06a1-4304-bdfc-e2964b8721bb.jpeg + * @return dev/default/2021/07/18/f4243eb2-06a1-4304-bdfc-e2964b8721bb.jpeg + */ + private String getStorePath(String filePath) { + String oldPath = filePath; + // 处理方式1 + String publicPath3 = minioConfig.getDomain() + "/" + minioConfig.getBucketName() + "/"; + filePath = filePath.replace(publicPath3, ""); + + if (oldPath.equals(filePath)) { + // 处理方式2 + String publicPath4 = minioConfig.getUrl() + "/" + minioConfig.getBucketName() + "/"; + filePath = filePath.replace(publicPath4, ""); + } + return filePath; + } } 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 index ac0311a2..3961fa7f 100644 --- 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 @@ -12,9 +12,11 @@ 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.apache.commons.lang3.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Primary; import org.springframework.stereotype.Service; import org.springframework.web.multipart.MultipartFile; @@ -28,6 +30,7 @@ import java.io.InputStream; * 参考:https://developer.qiniu.com/kodo/1239/java#upload-stream * 路径:【对象存储==>JAVASDK==>文件上传==>数据流上传】 */ +//@Primary @Service public class QiniuDfsServiceImpl implements IDfsService { private static final Logger log = LoggerFactory.getLogger(QiniuDfsServiceImpl.class); @@ -42,9 +45,10 @@ public class QiniuDfsServiceImpl implements IDfsService { @Override public String uploadFile(MultipartFile file, String modules) throws Exception { //key: 这里不能以/开头 - String newName = validateModule(file, null); + validateModule(file, modules); + String newName = extractFileNameSimple(file); //key: 这里不能以/开头 - String requestKey = "upload/" + "/" + newName; + String requestKey = "upload/" + StringUtils.defaultString(modules, "default") + "/" + newName; //这里增加一个前缀区分一下是测试环境还是正式环境 boolean isProd = "prod".equalsIgnoreCase(SpringUtil.getActiveProfile()); if (!isProd) { @@ -58,6 +62,7 @@ public class QiniuDfsServiceImpl implements IDfsService { String accessKey = qiniuKodoConfig.getAccessKey(); String secretKey = qiniuKodoConfig.getSecretKey(); String bucket = qiniuKodoConfig.getBucketName(); + String domain = qiniuKodoConfig.getDomain(); //默认不指定key的情况下,以文件内容的hash值作为文件名 String key = requestKey; @@ -68,8 +73,8 @@ public class QiniuDfsServiceImpl implements IDfsService { 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); + /// http://guangdong-oss.ityun.ltd/dev/upload/default/20210717-133e3b4a-6aad-418c-a040-7161fa37ee49.jpeg + return (domain + "/" + putRet.key).replace("//", "/") ; } catch (QiniuException ex) { Response r = ex.response; String json = null; @@ -98,6 +103,7 @@ public class QiniuDfsServiceImpl implements IDfsService { String key = getStorePath(fileUrl); try { bucketManager.delete(bucket, key); + return true; } catch (QiniuException ex) { //如果遇到异常,说明删除失败 log.error("【七牛云】-删除文件-失败 code:" + ex.code() + "=>" + ex.response.toString()); @@ -137,7 +143,8 @@ public class QiniuDfsServiceImpl implements IDfsService { /// 其中关于Region对象和机房的关系如下: ///Region region = Region.autoRegion(); ///Region region = Region.region0(); + ///Region region = Region.huanan(); //构造一个带指定 Region 对象的配置类 - return Region.huadong(); + return Region.autoRegion(); } } diff --git a/ruoyi-modules/ruoyi-file/src/main/resources/bootstrap.yml b/ruoyi-modules/ruoyi-file/src/main/resources/bootstrap.yml index 899210bf..759ed476 100644 --- a/ruoyi-modules/ruoyi-file/src/main/resources/bootstrap.yml +++ b/ruoyi-modules/ruoyi-file/src/main/resources/bootstrap.yml @@ -50,10 +50,11 @@ fdfs: # 文件服务器之4 Minio配置 minio: - url: http://192.168.254.100:9900 + url: http://10.16.58.152:9000 accessKey: D99KGE6ZTQXSATTJWU24 secretKey: QyVqGnhIQQE734UYSUFlGOZViE6+ZlDEfUG3NjhJ - bucketName: neusoft-appt + bucketName: appt-file + domain: https://image.bj.gov.cn # 文件服务器之5 aliyun oss aliyun-oss: @@ -63,3 +64,9 @@ aliyun-oss: endpoint: oss-cn-shanghai.aliyuncs.com domain: https://react-yuebaoxiao-pro.oss-cn-shanghai.aliyuncs.com +# 文件服务器之6 qiniu 七牛 kodo +qiniu: + access-key: pRYrSe_EW4sJHsQ6JyuiRYShA2JCLKtMhT-N4TQD + secret-key: CwTEh1kSLBdxBhIWfFz6h1GgDSokx97CYEV0cC1O + bucket-name: guangdong-oss + domain: http://guangdong-oss.ityun.ltd