From 7c5b144b90670e8d1a6568378eb3a930747b4b71 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E7=96=AF=E7=8B=82=E7=9A=84=E7=8B=AE=E5=AD=90li?=
<15040126243@163.com>
Date: Wed, 9 Feb 2022 11:38:09 +0800
Subject: [PATCH] =?UTF-8?q?add=20=E5=A2=9E=E5=8A=A0=20ruoyi-common-oss=20?=
=?UTF-8?q?=E6=A8=A1=E5=9D=97?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
pom.xml | 6 +
ruoyi-common/pom.xml | 1 +
ruoyi-common/ruoyi-common-bom/pom.xml | 7 +
ruoyi-common/ruoyi-common-oss/pom.xml | 53 +++++
.../common/oss/constant/OssConstant.java | 38 ++++
.../ruoyi/common/oss/entity/UploadResult.java | 24 +++
.../com/ruoyi/common/oss/enumd/OssEnumd.java | 52 +++++
.../ruoyi/common/oss/enumd/PolicyType.java | 51 +++++
.../common/oss/exception/OssException.java | 16 ++
.../ruoyi/common/oss/factory/OssFactory.java | 79 ++++++++
.../common/oss/properties/OssProperties.java | 48 +++++
.../common/oss/service/IOssStrategy.java | 67 +++++++
.../abstractd/AbstractOssStrategy.java | 64 ++++++
.../oss/service/impl/AliyunOssStrategy.java | 115 +++++++++++
.../oss/service/impl/MinioOssStrategy.java | 184 ++++++++++++++++++
.../oss/service/impl/QcloudOssStrategy.java | 124 ++++++++++++
.../oss/service/impl/QiniuOssStrategy.java | 127 ++++++++++++
.../main/resources/META-INF/spring.factories | 1 +
18 files changed, 1057 insertions(+)
create mode 100644 ruoyi-common/ruoyi-common-oss/pom.xml
create mode 100644 ruoyi-common/ruoyi-common-oss/src/main/java/com/ruoyi/common/oss/constant/OssConstant.java
create mode 100644 ruoyi-common/ruoyi-common-oss/src/main/java/com/ruoyi/common/oss/entity/UploadResult.java
create mode 100644 ruoyi-common/ruoyi-common-oss/src/main/java/com/ruoyi/common/oss/enumd/OssEnumd.java
create mode 100644 ruoyi-common/ruoyi-common-oss/src/main/java/com/ruoyi/common/oss/enumd/PolicyType.java
create mode 100644 ruoyi-common/ruoyi-common-oss/src/main/java/com/ruoyi/common/oss/exception/OssException.java
create mode 100644 ruoyi-common/ruoyi-common-oss/src/main/java/com/ruoyi/common/oss/factory/OssFactory.java
create mode 100644 ruoyi-common/ruoyi-common-oss/src/main/java/com/ruoyi/common/oss/properties/OssProperties.java
create mode 100644 ruoyi-common/ruoyi-common-oss/src/main/java/com/ruoyi/common/oss/service/IOssStrategy.java
create mode 100644 ruoyi-common/ruoyi-common-oss/src/main/java/com/ruoyi/common/oss/service/abstractd/AbstractOssStrategy.java
create mode 100644 ruoyi-common/ruoyi-common-oss/src/main/java/com/ruoyi/common/oss/service/impl/AliyunOssStrategy.java
create mode 100644 ruoyi-common/ruoyi-common-oss/src/main/java/com/ruoyi/common/oss/service/impl/MinioOssStrategy.java
create mode 100644 ruoyi-common/ruoyi-common-oss/src/main/java/com/ruoyi/common/oss/service/impl/QcloudOssStrategy.java
create mode 100644 ruoyi-common/ruoyi-common-oss/src/main/java/com/ruoyi/common/oss/service/impl/QiniuOssStrategy.java
create mode 100644 ruoyi-common/ruoyi-common-oss/src/main/resources/META-INF/spring.factories
diff --git a/pom.xml b/pom.xml
index ad7aa0a4..6496e14d 100644
--- a/pom.xml
+++ b/pom.xml
@@ -49,6 +49,12 @@
3.0.3
1.28.0
+
+ 7.9.2
+ 3.14.0
+ 5.6.68
+ 8.3.5
+
localhost
http://${docker.registry.url}:2375
diff --git a/ruoyi-common/pom.xml b/ruoyi-common/pom.xml
index fbc15739..8d5d11c3 100644
--- a/ruoyi-common/pom.xml
+++ b/ruoyi-common/pom.xml
@@ -25,6 +25,7 @@
ruoyi-common-dubbo
ruoyi-common-seata
ruoyi-common-loadbalancer
+ ruoyi-common-oss
ruoyi-common
diff --git a/ruoyi-common/ruoyi-common-bom/pom.xml b/ruoyi-common/ruoyi-common-bom/pom.xml
index f9ead887..85623563 100644
--- a/ruoyi-common/ruoyi-common-bom/pom.xml
+++ b/ruoyi-common/ruoyi-common-bom/pom.xml
@@ -114,6 +114,13 @@
ruoyi-common-loadbalancer
${project.version}
+
+
+ com.ruoyi
+ ruoyi-common-oss
+ ${project.version}
+
+
diff --git a/ruoyi-common/ruoyi-common-oss/pom.xml b/ruoyi-common/ruoyi-common-oss/pom.xml
new file mode 100644
index 00000000..d3b83ce9
--- /dev/null
+++ b/ruoyi-common/ruoyi-common-oss/pom.xml
@@ -0,0 +1,53 @@
+
+
+
+ com.ruoyi
+ ruoyi-common
+ 0.5.0
+
+ 4.0.0
+
+ ruoyi-common-oss
+
+
+ ruoyi-common-oss oss服务
+
+
+
+
+
+ com.ruoyi
+ ruoyi-common-redis
+
+
+
+ com.qiniu
+ qiniu-java-sdk
+ ${qiniu.version}
+
+
+ com.aliyun.oss
+ aliyun-sdk-oss
+ ${aliyun.oss.version}
+
+
+ com.qcloud
+ cos_api
+ ${qcloud.cos.version}
+
+
+ org.slf4j
+ slf4j-log4j12
+
+
+
+
+ io.minio
+ minio
+ ${minio.version}
+
+
+
+
diff --git a/ruoyi-common/ruoyi-common-oss/src/main/java/com/ruoyi/common/oss/constant/OssConstant.java b/ruoyi-common/ruoyi-common-oss/src/main/java/com/ruoyi/common/oss/constant/OssConstant.java
new file mode 100644
index 00000000..3e5730e4
--- /dev/null
+++ b/ruoyi-common/ruoyi-common-oss/src/main/java/com/ruoyi/common/oss/constant/OssConstant.java
@@ -0,0 +1,38 @@
+package com.ruoyi.common.oss.constant;
+
+import java.util.Arrays;
+import java.util.List;
+
+/**
+ * 对象存储常量
+ *
+ * @author Lion Li
+ */
+public class OssConstant {
+
+ /**
+ * OSS模块KEY
+ */
+ public static final String SYS_OSS_KEY = "sys_oss:";
+
+ /**
+ * 对象存储配置KEY
+ */
+ public static final String OSS_CONFIG_KEY = "OssConfig";
+
+ /**
+ * 缓存配置KEY
+ */
+ public static final String CACHE_CONFIG_KEY = SYS_OSS_KEY + OSS_CONFIG_KEY;
+
+ /**
+ * 预览列表资源开关Key
+ */
+ public static final String PEREVIEW_LIST_RESOURCE_KEY = "sys.oss.previewListResource";
+
+ /**
+ * 系统数据ids
+ */
+ public static final List SYSTEM_DATA_IDS = Arrays.asList(1, 2, 3, 4);
+
+}
diff --git a/ruoyi-common/ruoyi-common-oss/src/main/java/com/ruoyi/common/oss/entity/UploadResult.java b/ruoyi-common/ruoyi-common-oss/src/main/java/com/ruoyi/common/oss/entity/UploadResult.java
new file mode 100644
index 00000000..fd2e7fc1
--- /dev/null
+++ b/ruoyi-common/ruoyi-common-oss/src/main/java/com/ruoyi/common/oss/entity/UploadResult.java
@@ -0,0 +1,24 @@
+package com.ruoyi.common.oss.entity;
+
+import lombok.Builder;
+import lombok.Data;
+
+/**
+ * 上传返回体
+ *
+ * @author Lion Li
+ */
+@Data
+@Builder
+public class UploadResult {
+
+ /**
+ * 文件路径
+ */
+ private String url;
+
+ /**
+ * 文件名
+ */
+ private String filename;
+}
diff --git a/ruoyi-common/ruoyi-common-oss/src/main/java/com/ruoyi/common/oss/enumd/OssEnumd.java b/ruoyi-common/ruoyi-common-oss/src/main/java/com/ruoyi/common/oss/enumd/OssEnumd.java
new file mode 100644
index 00000000..cc281381
--- /dev/null
+++ b/ruoyi-common/ruoyi-common-oss/src/main/java/com/ruoyi/common/oss/enumd/OssEnumd.java
@@ -0,0 +1,52 @@
+package com.ruoyi.common.oss.enumd;
+
+import com.ruoyi.common.oss.service.impl.AliyunOssStrategy;
+import com.ruoyi.common.oss.service.impl.MinioOssStrategy;
+import com.ruoyi.common.oss.service.impl.QcloudOssStrategy;
+import com.ruoyi.common.oss.service.impl.QiniuOssStrategy;
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+
+/**
+ * 对象存储服务商枚举
+ *
+ * @author Lion Li
+ */
+@Getter
+@AllArgsConstructor
+public enum OssEnumd {
+
+ /**
+ * 七牛云
+ */
+ QINIU("qiniu", QiniuOssStrategy.class),
+
+ /**
+ * 阿里云
+ */
+ ALIYUN("aliyun", AliyunOssStrategy.class),
+
+ /**
+ * 腾讯云
+ */
+ QCLOUD("qcloud", QcloudOssStrategy.class),
+
+ /**
+ * minio
+ */
+ MINIO("minio", MinioOssStrategy.class);
+
+ private final String value;
+
+ private final Class> beanClass;
+
+ public static OssEnumd find(String value) {
+ for (OssEnumd enumd : values()) {
+ if (enumd.getValue().equals(value)) {
+ return enumd;
+ }
+ }
+ return null;
+ }
+
+}
diff --git a/ruoyi-common/ruoyi-common-oss/src/main/java/com/ruoyi/common/oss/enumd/PolicyType.java b/ruoyi-common/ruoyi-common-oss/src/main/java/com/ruoyi/common/oss/enumd/PolicyType.java
new file mode 100644
index 00000000..704874bd
--- /dev/null
+++ b/ruoyi-common/ruoyi-common-oss/src/main/java/com/ruoyi/common/oss/enumd/PolicyType.java
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2018-2028, Chill Zhuang All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * Neither the name of the dreamlu.net developer nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ * Author: Chill 庄骞 (smallchill@163.com)
+ */
+package com.ruoyi.common.oss.enumd;
+
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+
+/**
+ * minio策略配置
+ *
+ * @author Lion Li
+ */
+@Getter
+@AllArgsConstructor
+public enum PolicyType {
+
+ /**
+ * 只读
+ */
+ READ("read-only"),
+
+ /**
+ * 只写
+ */
+ WRITE("write-only"),
+
+ /**
+ * 读写
+ */
+ READ_WRITE("read-write");
+
+ /**
+ * 类型
+ */
+ private final String type;
+
+}
diff --git a/ruoyi-common/ruoyi-common-oss/src/main/java/com/ruoyi/common/oss/exception/OssException.java b/ruoyi-common/ruoyi-common-oss/src/main/java/com/ruoyi/common/oss/exception/OssException.java
new file mode 100644
index 00000000..061165b4
--- /dev/null
+++ b/ruoyi-common/ruoyi-common-oss/src/main/java/com/ruoyi/common/oss/exception/OssException.java
@@ -0,0 +1,16 @@
+package com.ruoyi.common.oss.exception;
+
+/**
+ * OSS异常类
+ *
+ * @author Lion Li
+ */
+public class OssException extends RuntimeException {
+
+ private static final long serialVersionUID = 1L;
+
+ public OssException(String msg) {
+ super(msg);
+ }
+
+}
diff --git a/ruoyi-common/ruoyi-common-oss/src/main/java/com/ruoyi/common/oss/factory/OssFactory.java b/ruoyi-common/ruoyi-common-oss/src/main/java/com/ruoyi/common/oss/factory/OssFactory.java
new file mode 100644
index 00000000..107d646d
--- /dev/null
+++ b/ruoyi-common/ruoyi-common-oss/src/main/java/com/ruoyi/common/oss/factory/OssFactory.java
@@ -0,0 +1,79 @@
+package com.ruoyi.common.oss.factory;
+
+import com.ruoyi.common.core.utils.JsonUtils;
+import com.ruoyi.common.core.utils.SpringUtils;
+import com.ruoyi.common.core.utils.StringUtils;
+import com.ruoyi.common.oss.constant.OssConstant;
+import com.ruoyi.common.oss.enumd.OssEnumd;
+import com.ruoyi.common.oss.exception.OssException;
+import com.ruoyi.common.oss.properties.OssProperties;
+import com.ruoyi.common.oss.service.IOssStrategy;
+import com.ruoyi.common.oss.service.abstractd.AbstractOssStrategy;
+import com.ruoyi.common.redis.utils.RedisUtils;
+import lombok.extern.slf4j.Slf4j;
+
+/**
+ * 文件上传Factory
+ *
+ * @author Lion Li
+ */
+@Slf4j
+public class OssFactory {
+
+ /**
+ * 初始化工厂
+ */
+ public static void init() {
+ log.info("初始化OSS工厂");
+ RedisUtils.subscribe(OssConstant.CACHE_CONFIG_KEY, String.class, type -> {
+ AbstractOssStrategy strategy = getStrategy(type);
+ // 未初始化不处理
+ if (strategy.isInit) {
+ refresh(type);
+ log.info("订阅刷新OSS配置 => " + type);
+ }
+ });
+ }
+
+ /**
+ * 获取默认实例
+ */
+ public static IOssStrategy instance() {
+ // 获取redis 默认类型
+ String type = RedisUtils.getCacheObject(OssConstant.CACHE_CONFIG_KEY);
+ if (StringUtils.isEmpty(type)) {
+ throw new OssException("文件存储服务类型无法找到!");
+ }
+ return instance(type);
+ }
+
+ /**
+ * 根据类型获取实例
+ */
+ public static IOssStrategy instance(String type) {
+ OssEnumd enumd = OssEnumd.find(type);
+ if (enumd == null) {
+ throw new OssException("文件存储服务类型无法找到!");
+ }
+ AbstractOssStrategy strategy = getStrategy(type);
+ if (!strategy.isInit) {
+ refresh(type);
+ }
+ return strategy;
+ }
+
+ private static void refresh(String type) {
+ Object json = RedisUtils.getCacheObject(OssConstant.SYS_OSS_KEY + type);
+ OssProperties properties = JsonUtils.parseObject(json.toString(), OssProperties.class);
+ if (properties == null) {
+ throw new OssException("系统异常, '" + type + "'配置信息不存在!");
+ }
+ getStrategy(type).init(properties);
+ }
+
+ private static AbstractOssStrategy getStrategy(String type) {
+ OssEnumd enumd = OssEnumd.find(type);
+ return (AbstractOssStrategy) SpringUtils.getBean(enumd.getBeanClass());
+ }
+
+}
diff --git a/ruoyi-common/ruoyi-common-oss/src/main/java/com/ruoyi/common/oss/properties/OssProperties.java b/ruoyi-common/ruoyi-common-oss/src/main/java/com/ruoyi/common/oss/properties/OssProperties.java
new file mode 100644
index 00000000..2975f951
--- /dev/null
+++ b/ruoyi-common/ruoyi-common-oss/src/main/java/com/ruoyi/common/oss/properties/OssProperties.java
@@ -0,0 +1,48 @@
+package com.ruoyi.common.oss.properties;
+
+import lombok.Data;
+
+/**
+ * OSS对象存储 配置属性
+ *
+ * @author Lion Li
+ */
+@Data
+public class OssProperties {
+
+ /**
+ * 域名
+ */
+ private String endpoint;
+
+ /**
+ * 前缀
+ */
+ private String prefix;
+
+ /**
+ * ACCESS_KEY
+ */
+ private String accessKey;
+
+ /**
+ * SECRET_KEY
+ */
+ private String secretKey;
+
+ /**
+ * 存储空间名
+ */
+ private String bucketName;
+
+ /**
+ * 存储区域
+ */
+ private String region;
+
+ /**
+ * 是否https(Y=是,N=否)
+ */
+ private String isHttps;
+
+}
diff --git a/ruoyi-common/ruoyi-common-oss/src/main/java/com/ruoyi/common/oss/service/IOssStrategy.java b/ruoyi-common/ruoyi-common-oss/src/main/java/com/ruoyi/common/oss/service/IOssStrategy.java
new file mode 100644
index 00000000..6e1de5b1
--- /dev/null
+++ b/ruoyi-common/ruoyi-common-oss/src/main/java/com/ruoyi/common/oss/service/IOssStrategy.java
@@ -0,0 +1,67 @@
+package com.ruoyi.common.oss.service;
+
+
+import com.ruoyi.common.oss.entity.UploadResult;
+import com.ruoyi.common.oss.enumd.OssEnumd;
+
+import java.io.InputStream;
+
+/**
+ * 对象存储策略
+ *
+ * @author Lion Li
+ */
+public interface IOssStrategy {
+
+ void createBucket();
+
+ /**
+ * 获取服务商类型
+ * @return
+ */
+ OssEnumd getServiceType();
+
+ /**
+ * 文件上传
+ *
+ * @param data 文件字节数组
+ * @param path 文件路径,包含文件名
+ * @return 返回http地址
+ */
+ UploadResult upload(byte[] data, String path, String contentType);
+
+ /**
+ * 文件删除
+ *
+ * @param path 文件路径,包含文件名
+ */
+ void delete(String path);
+
+ /**
+ * 文件上传
+ *
+ * @param data 文件字节数组
+ * @param suffix 后缀
+ * @return 返回http地址
+ */
+ UploadResult uploadSuffix(byte[] data, String suffix, String contentType);
+
+ /**
+ * 文件上传
+ *
+ * @param inputStream 字节流
+ * @param path 文件路径,包含文件名
+ * @return 返回http地址
+ */
+ UploadResult upload(InputStream inputStream, String path, String contentType);
+
+ /**
+ * 文件上传
+ *
+ * @param inputStream 字节流
+ * @param suffix 后缀
+ * @return 返回http地址
+ */
+ UploadResult uploadSuffix(InputStream inputStream, String suffix, String contentType);
+
+}
diff --git a/ruoyi-common/ruoyi-common-oss/src/main/java/com/ruoyi/common/oss/service/abstractd/AbstractOssStrategy.java b/ruoyi-common/ruoyi-common-oss/src/main/java/com/ruoyi/common/oss/service/abstractd/AbstractOssStrategy.java
new file mode 100644
index 00000000..d837800b
--- /dev/null
+++ b/ruoyi-common/ruoyi-common-oss/src/main/java/com/ruoyi/common/oss/service/abstractd/AbstractOssStrategy.java
@@ -0,0 +1,64 @@
+package com.ruoyi.common.oss.service.abstractd;
+
+import cn.hutool.core.io.IoUtil;
+import cn.hutool.core.util.IdUtil;
+import com.ruoyi.common.core.utils.DateUtils;
+import com.ruoyi.common.core.utils.StringUtils;
+import com.ruoyi.common.oss.entity.UploadResult;
+import com.ruoyi.common.oss.enumd.OssEnumd;
+import com.ruoyi.common.oss.properties.OssProperties;
+import com.ruoyi.common.oss.service.IOssStrategy;
+
+import java.io.InputStream;
+
+/**
+ * 对象存储策略(支持七牛、阿里云、腾讯云、minio)
+ *
+ * @author Lion Li
+ */
+public abstract class AbstractOssStrategy implements IOssStrategy {
+
+ protected OssProperties properties;
+ public boolean isInit = false;
+
+ public void init(OssProperties properties) {
+ this.properties = properties;
+ }
+
+ @Override
+ public abstract void createBucket();
+
+ @Override
+ public abstract OssEnumd getServiceType();
+
+ public String getPath(String prefix, String suffix) {
+ // 生成uuid
+ String uuid = IdUtil.fastSimpleUUID();
+ // 文件路径
+ String path = DateUtils.datePath() + "/" + uuid;
+ if (StringUtils.isNotBlank(prefix)) {
+ path = prefix + "/" + path;
+ }
+ return path + suffix;
+ }
+
+ @Override
+ public abstract UploadResult upload(byte[] data, String path, String contentType);
+
+ @Override
+ public abstract void delete(String path);
+
+ @Override
+ public UploadResult upload(InputStream inputStream, String path, String contentType) {
+ byte[] data = IoUtil.readBytes(inputStream);
+ return this.upload(data, path, contentType);
+ }
+
+ @Override
+ public abstract UploadResult uploadSuffix(byte[] data, String suffix, String contentType);
+
+ @Override
+ public abstract UploadResult uploadSuffix(InputStream inputStream, String suffix, String contentType);
+
+ public abstract String getEndpointLink();
+}
diff --git a/ruoyi-common/ruoyi-common-oss/src/main/java/com/ruoyi/common/oss/service/impl/AliyunOssStrategy.java b/ruoyi-common/ruoyi-common-oss/src/main/java/com/ruoyi/common/oss/service/impl/AliyunOssStrategy.java
new file mode 100644
index 00000000..f0d3fb35
--- /dev/null
+++ b/ruoyi-common/ruoyi-common-oss/src/main/java/com/ruoyi/common/oss/service/impl/AliyunOssStrategy.java
@@ -0,0 +1,115 @@
+package com.ruoyi.common.oss.service.impl;
+
+import com.aliyun.oss.ClientConfiguration;
+import com.aliyun.oss.OSSClient;
+import com.aliyun.oss.common.auth.DefaultCredentialProvider;
+import com.aliyun.oss.model.CannedAccessControlList;
+import com.aliyun.oss.model.CreateBucketRequest;
+import com.aliyun.oss.model.ObjectMetadata;
+import com.aliyun.oss.model.PutObjectRequest;
+import com.ruoyi.common.core.utils.StringUtils;
+import com.ruoyi.common.oss.entity.UploadResult;
+import com.ruoyi.common.oss.enumd.OssEnumd;
+import com.ruoyi.common.oss.exception.OssException;
+import com.ruoyi.common.oss.properties.OssProperties;
+import com.ruoyi.common.oss.service.abstractd.AbstractOssStrategy;
+import org.springframework.stereotype.Component;
+
+import java.io.ByteArrayInputStream;
+import java.io.InputStream;
+
+/**
+ * 阿里云存储策略
+ *
+ * @author Lion Li
+ */
+@Component
+public class AliyunOssStrategy extends AbstractOssStrategy {
+
+ private OSSClient client;
+
+ @Override
+ public void init(OssProperties ossProperties) {
+ super.init(ossProperties);
+ try {
+ ClientConfiguration configuration = new ClientConfiguration();
+ DefaultCredentialProvider credentialProvider = new DefaultCredentialProvider(
+ properties.getAccessKey(), properties.getSecretKey());
+ client = new OSSClient(properties.getEndpoint(), credentialProvider, configuration);
+ createBucket();
+ } catch (Exception e) {
+ throw new OssException("阿里云存储配置错误! 请检查系统配置:[" + e.getMessage() + "]");
+ }
+ isInit = true;
+ }
+
+ @Override
+ public void createBucket() {
+ try {
+ String bucketName = properties.getBucketName();
+ if (client.doesBucketExist(bucketName)) {
+ return;
+ }
+ CreateBucketRequest createBucketRequest = new CreateBucketRequest(bucketName);
+ createBucketRequest.setCannedACL(CannedAccessControlList.PublicRead);
+ client.createBucket(createBucketRequest);
+ } catch (Exception e) {
+ throw new OssException("创建Bucket失败, 请核对阿里云配置信息:[" + e.getMessage() + "]");
+ }
+ }
+
+ @Override
+ public OssEnumd getServiceType() {
+ return OssEnumd.ALIYUN;
+ }
+
+ @Override
+ public UploadResult upload(byte[] data, String path, String contentType) {
+ return upload(new ByteArrayInputStream(data), path, contentType);
+ }
+
+ @Override
+ public UploadResult upload(InputStream inputStream, String path, String contentType) {
+ try {
+ ObjectMetadata metadata = new ObjectMetadata();
+ metadata.setContentType(contentType);
+ client.putObject(new PutObjectRequest(properties.getBucketName(), path, inputStream, metadata));
+ } catch (Exception e) {
+ throw new OssException("上传文件失败,请检查阿里云配置信息:[" + e.getMessage() + "]");
+ }
+ return UploadResult.builder().url(getEndpointLink() + "/" + path).filename(path).build(); }
+
+ @Override
+ public void delete(String path) {
+ path = path.replace(getEndpointLink() + "/", "");
+ try {
+ client.deleteObject(properties.getBucketName(), path);
+ } catch (Exception e) {
+ throw new OssException("上传文件失败,请检查阿里云配置信息:[" + e.getMessage() + "]");
+ }
+ }
+
+ @Override
+ public UploadResult uploadSuffix(byte[] data, String suffix, String contentType) {
+ return upload(data, getPath(properties.getPrefix(), suffix), contentType);
+ }
+
+ @Override
+ public UploadResult uploadSuffix(InputStream inputStream, String suffix, String contentType) {
+ return upload(inputStream, getPath(properties.getPrefix(), suffix), contentType);
+ }
+
+ @Override
+ public String getEndpointLink() {
+ String endpoint = properties.getEndpoint();
+ StringBuilder sb = new StringBuilder(endpoint);
+ if (StringUtils.containsAnyIgnoreCase(endpoint, "http://")) {
+ sb.insert(7, properties.getBucketName() + ".");
+ } else if (StringUtils.containsAnyIgnoreCase(endpoint, "https://")) {
+ sb.insert(8, properties.getBucketName() + ".");
+ } else {
+ throw new OssException("Endpoint配置错误");
+ }
+ return sb.toString();
+ }
+}
diff --git a/ruoyi-common/ruoyi-common-oss/src/main/java/com/ruoyi/common/oss/service/impl/MinioOssStrategy.java b/ruoyi-common/ruoyi-common-oss/src/main/java/com/ruoyi/common/oss/service/impl/MinioOssStrategy.java
new file mode 100644
index 00000000..50d52b8b
--- /dev/null
+++ b/ruoyi-common/ruoyi-common-oss/src/main/java/com/ruoyi/common/oss/service/impl/MinioOssStrategy.java
@@ -0,0 +1,184 @@
+package com.ruoyi.common.oss.service.impl;
+
+import com.ruoyi.common.core.utils.StringUtils;
+import com.ruoyi.common.oss.entity.UploadResult;
+import com.ruoyi.common.oss.enumd.OssEnumd;
+import com.ruoyi.common.oss.enumd.PolicyType;
+import com.ruoyi.common.oss.exception.OssException;
+import com.ruoyi.common.oss.properties.OssProperties;
+import com.ruoyi.common.oss.service.abstractd.AbstractOssStrategy;
+import io.minio.*;
+import org.springframework.http.MediaType;
+import org.springframework.stereotype.Component;
+
+import java.io.ByteArrayInputStream;
+import java.io.InputStream;
+
+/**
+ * minio存储策略
+ *
+ * @author Lion Li
+ */
+@Component
+public class MinioOssStrategy extends AbstractOssStrategy {
+
+ private MinioClient minioClient;
+
+ @Override
+ public void init(OssProperties ossProperties) {
+ super.init(ossProperties);
+ try {
+ minioClient = MinioClient.builder()
+ .endpoint(properties.getEndpoint())
+ .credentials(properties.getAccessKey(), properties.getSecretKey())
+ .build();
+ createBucket();
+ } catch (Exception e) {
+ throw new OssException("Minio存储配置错误! 请检查系统配置:[" + e.getMessage() + "]");
+ }
+ isInit = true;
+ }
+
+ @Override
+ public void createBucket() {
+ try {
+ String bucketName = properties.getBucketName();
+ boolean exists = minioClient.bucketExists(BucketExistsArgs.builder().bucket(bucketName).build());
+ if (exists) {
+ return;
+ }
+ // 不存在就创建桶
+ minioClient.makeBucket(MakeBucketArgs.builder().bucket(bucketName).build());
+ minioClient.setBucketPolicy(SetBucketPolicyArgs.builder()
+ .bucket(bucketName)
+ .config(getPolicy(bucketName, PolicyType.READ))
+ .build());
+ } catch (Exception e) {
+ throw new OssException("创建Bucket失败, 请核对Minio配置信息:[" + e.getMessage() + "]");
+ }
+ }
+
+ @Override
+ public OssEnumd getServiceType() {
+ return OssEnumd.MINIO;
+ }
+
+ @Override
+ public UploadResult upload(byte[] data, String path, String contentType) {
+ return upload(new ByteArrayInputStream(data), path, contentType);
+ }
+
+ @Override
+ public UploadResult upload(InputStream inputStream, String path, String contentType) {
+ try {
+ minioClient.putObject(PutObjectArgs.builder()
+ .bucket(properties.getBucketName())
+ .object(path)
+ .contentType(StringUtils.blankToDefault(contentType, MediaType.APPLICATION_OCTET_STREAM_VALUE))
+ .stream(inputStream, inputStream.available(), -1)
+ .build());
+ } catch (Exception e) {
+ throw new OssException("上传文件失败,请核对Minio配置信息:[" + e.getMessage() + "]");
+ }
+ return UploadResult.builder().url(getEndpointLink() + "/" + path).filename(path).build();
+ }
+
+ @Override
+ public void delete(String path) {
+ path = path.replace(getEndpointLink() + "/", "");
+ try {
+ minioClient.removeObject(RemoveObjectArgs.builder()
+ .bucket(properties.getBucketName())
+ .object(path)
+ .build());
+ } catch (Exception e) {
+ throw new OssException(e.getMessage());
+ }
+ }
+
+ @Override
+ public UploadResult uploadSuffix(byte[] data, String suffix, String contentType) {
+ return upload(data, getPath(properties.getPrefix(), suffix), contentType);
+ }
+
+ @Override
+ public UploadResult uploadSuffix(InputStream inputStream, String suffix, String contentType) {
+ return upload(inputStream, getPath(properties.getPrefix(), suffix), contentType);
+ }
+
+ @Override
+ public String getEndpointLink() {
+ return properties.getEndpoint() + "/" + properties.getBucketName();
+ }
+
+ private String getPolicy(String bucketName, PolicyType policyType) {
+ StringBuilder builder = new StringBuilder();
+ builder.append("{\n");
+ builder.append(" \"Statement\": [\n");
+ builder.append(" {\n");
+ builder.append(" \"Action\": [\n");
+ if (policyType == PolicyType.WRITE) {
+ builder.append(" \"s3:GetBucketLocation\",\n");
+ builder.append(" \"s3:ListBucketMultipartUploads\"\n");
+ } else if (policyType == PolicyType.READ_WRITE) {
+ builder.append(" \"s3:GetBucketLocation\",\n");
+ builder.append(" \"s3:ListBucket\",\n");
+ builder.append(" \"s3:ListBucketMultipartUploads\"\n");
+ } else {
+ builder.append(" \"s3:GetBucketLocation\"\n");
+ }
+ builder.append(" ],\n");
+ builder.append(" \"Effect\": \"Allow\",\n");
+ builder.append(" \"Principal\": \"*\",\n");
+ builder.append(" \"Resource\": \"arn:aws:s3:::");
+ builder.append(bucketName);
+ builder.append("\"\n");
+ builder.append(" },\n");
+ if (PolicyType.READ.equals(policyType)) {
+ builder.append(" {\n");
+ builder.append(" \"Action\": [\n");
+ builder.append(" \"s3:ListBucket\"\n");
+ builder.append(" ],\n");
+ builder.append(" \"Effect\": \"Deny\",\n");
+ builder.append(" \"Principal\": \"*\",\n");
+ builder.append(" \"Resource\": \"arn:aws:s3:::");
+ builder.append(bucketName);
+ builder.append("\"\n");
+ builder.append(" },\n");
+ }
+ builder.append(" {\n");
+ builder.append(" \"Action\": ");
+ switch (policyType) {
+ case WRITE:
+ builder.append("[\n");
+ builder.append(" \"s3:AbortMultipartUpload\",\n");
+ builder.append(" \"s3:DeleteObject\",\n");
+ builder.append(" \"s3:ListMultipartUploadParts\",\n");
+ builder.append(" \"s3:PutObject\"\n");
+ builder.append(" ],\n");
+ break;
+ case READ_WRITE:
+ builder.append("[\n");
+ builder.append(" \"s3:AbortMultipartUpload\",\n");
+ builder.append(" \"s3:DeleteObject\",\n");
+ builder.append(" \"s3:GetObject\",\n");
+ builder.append(" \"s3:ListMultipartUploadParts\",\n");
+ builder.append(" \"s3:PutObject\"\n");
+ builder.append(" ],\n");
+ break;
+ default:
+ builder.append("\"s3:GetObject\",\n");
+ break;
+ }
+ builder.append(" \"Effect\": \"Allow\",\n");
+ builder.append(" \"Principal\": \"*\",\n");
+ builder.append(" \"Resource\": \"arn:aws:s3:::");
+ builder.append(bucketName);
+ builder.append("/*\"\n");
+ builder.append(" }\n");
+ builder.append(" ],\n");
+ builder.append(" \"Version\": \"2012-10-17\"\n");
+ builder.append("}\n");
+ return builder.toString();
+ }
+}
diff --git a/ruoyi-common/ruoyi-common-oss/src/main/java/com/ruoyi/common/oss/service/impl/QcloudOssStrategy.java b/ruoyi-common/ruoyi-common-oss/src/main/java/com/ruoyi/common/oss/service/impl/QcloudOssStrategy.java
new file mode 100644
index 00000000..6c19b346
--- /dev/null
+++ b/ruoyi-common/ruoyi-common-oss/src/main/java/com/ruoyi/common/oss/service/impl/QcloudOssStrategy.java
@@ -0,0 +1,124 @@
+package com.ruoyi.common.oss.service.impl;
+
+import com.qcloud.cos.COSClient;
+import com.qcloud.cos.ClientConfig;
+import com.qcloud.cos.auth.BasicCOSCredentials;
+import com.qcloud.cos.auth.COSCredentials;
+import com.qcloud.cos.http.HttpProtocol;
+import com.qcloud.cos.model.*;
+import com.qcloud.cos.region.Region;
+import com.ruoyi.common.core.utils.StringUtils;
+import com.ruoyi.common.oss.entity.UploadResult;
+import com.ruoyi.common.oss.enumd.OssEnumd;
+import com.ruoyi.common.oss.exception.OssException;
+import com.ruoyi.common.oss.properties.OssProperties;
+import com.ruoyi.common.oss.service.abstractd.AbstractOssStrategy;
+import org.springframework.stereotype.Component;
+
+import java.io.ByteArrayInputStream;
+import java.io.InputStream;
+
+/**
+ * 腾讯云存储策略
+ *
+ * @author Lion Li
+ */
+@Component
+public class QcloudOssStrategy extends AbstractOssStrategy {
+
+ private COSClient client;
+
+ @Override
+ public void init(OssProperties ossProperties) {
+ super.init(ossProperties);
+ try {
+ COSCredentials credentials = new BasicCOSCredentials(
+ properties.getAccessKey(), properties.getSecretKey());
+ // 初始化客户端配置
+ ClientConfig clientConfig = new ClientConfig();
+ // 设置bucket所在的区域,华南:gz 华北:tj 华东:sh
+ clientConfig.setRegion(new Region(properties.getRegion()));
+ if ("Y".equals(properties.getIsHttps())) {
+ clientConfig.setHttpProtocol(HttpProtocol.https);
+ } else {
+ clientConfig.setHttpProtocol(HttpProtocol.http);
+ }
+ client = new COSClient(credentials, clientConfig);
+ createBucket();
+ } catch (Exception e) {
+ throw new OssException("腾讯云存储配置错误! 请检查系统配置:[" + e.getMessage() + "]");
+ }
+ isInit = true;
+ }
+
+ @Override
+ public void createBucket() {
+ try {
+ String bucketName = properties.getBucketName();
+ if (client.doesBucketExist(bucketName)) {
+ return;
+ }
+ CreateBucketRequest createBucketRequest = new CreateBucketRequest(bucketName);
+ createBucketRequest.setCannedAcl(CannedAccessControlList.PublicRead);
+ client.createBucket(createBucketRequest);
+ } catch (Exception e) {
+ throw new OssException("创建Bucket失败, 请核对腾讯云配置信息:[" + e.getMessage() + "]");
+ }
+ }
+
+ @Override
+ public OssEnumd getServiceType() {
+ return OssEnumd.QCLOUD;
+ }
+
+ @Override
+ public UploadResult upload(byte[] data, String path, String contentType) {
+ return upload(new ByteArrayInputStream(data), path, contentType);
+ }
+
+ @Override
+ public UploadResult upload(InputStream inputStream, String path, String contentType) {
+ try {
+ ObjectMetadata metadata = new ObjectMetadata();
+ metadata.setContentType(contentType);
+ client.putObject(new PutObjectRequest(properties.getBucketName(), path, inputStream, metadata));
+ } catch (Exception e) {
+ throw new OssException("上传文件失败,请检查腾讯云配置信息:[" + e.getMessage() + "]");
+ }
+ return UploadResult.builder().url(getEndpointLink() + "/" + path).filename(path).build();
+ }
+
+ @Override
+ public void delete(String path) {
+ path = path.replace(getEndpointLink() + "/", "");
+ try {
+ client.deleteObject(new DeleteObjectRequest(properties.getBucketName(), path));
+ } catch (Exception e) {
+ throw new OssException("上传文件失败,请检腾讯云查配置信息:[" + e.getMessage() + "]");
+ }
+ }
+
+ @Override
+ public UploadResult uploadSuffix(byte[] data, String suffix, String contentType) {
+ return upload(data, getPath(properties.getPrefix(), suffix), contentType);
+ }
+
+ @Override
+ public UploadResult uploadSuffix(InputStream inputStream, String suffix, String contentType) {
+ return upload(inputStream, getPath(properties.getPrefix(), suffix), contentType);
+ }
+
+ @Override
+ public String getEndpointLink() {
+ String endpoint = properties.getEndpoint();
+ StringBuilder sb = new StringBuilder(endpoint);
+ if (StringUtils.containsAnyIgnoreCase(endpoint, "http://")) {
+ sb.insert(7, properties.getBucketName() + ".");
+ } else if (StringUtils.containsAnyIgnoreCase(endpoint, "https://")) {
+ sb.insert(8, properties.getBucketName() + ".");
+ } else {
+ throw new OssException("Endpoint配置错误");
+ }
+ return sb.toString();
+ }
+}
diff --git a/ruoyi-common/ruoyi-common-oss/src/main/java/com/ruoyi/common/oss/service/impl/QiniuOssStrategy.java b/ruoyi-common/ruoyi-common-oss/src/main/java/com/ruoyi/common/oss/service/impl/QiniuOssStrategy.java
new file mode 100644
index 00000000..e35ed240
--- /dev/null
+++ b/ruoyi-common/ruoyi-common-oss/src/main/java/com/ruoyi/common/oss/service/impl/QiniuOssStrategy.java
@@ -0,0 +1,127 @@
+package com.ruoyi.common.oss.service.impl;
+
+import cn.hutool.core.util.ArrayUtil;
+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.util.Auth;
+import com.ruoyi.common.oss.entity.UploadResult;
+import com.ruoyi.common.oss.enumd.OssEnumd;
+import com.ruoyi.common.oss.exception.OssException;
+import com.ruoyi.common.oss.properties.OssProperties;
+import com.ruoyi.common.oss.service.abstractd.AbstractOssStrategy;
+import org.springframework.stereotype.Component;
+
+import java.io.InputStream;
+
+/**
+ * 七牛云存储策略
+ *
+ * @author Lion Li
+ */
+@Component
+public class QiniuOssStrategy extends AbstractOssStrategy {
+
+ private UploadManager uploadManager;
+ private BucketManager bucketManager;
+ private Auth auth;
+
+
+ @Override
+ public void init(OssProperties ossProperties) {
+ super.init(ossProperties);
+ try {
+ Configuration config = new Configuration(getRegion(properties.getRegion()));
+ // https设置
+ config.useHttpsDomains = false;
+ config.useHttpsDomains = "Y".equals(properties.getIsHttps());
+ uploadManager = new UploadManager(config);
+ auth = Auth.create(properties.getAccessKey(), properties.getSecretKey());
+ bucketManager = new BucketManager(auth, config);
+ createBucket();
+ } catch (Exception e) {
+ throw new OssException("七牛云存储配置错误! 请检查系统配置:[" + e.getMessage() + "]");
+ }
+ isInit = true;
+ }
+
+ @Override
+ public void createBucket() {
+ try {
+ String bucketName = properties.getBucketName();
+ if (ArrayUtil.contains(bucketManager.buckets(), bucketName)) {
+ return;
+ }
+ bucketManager.createBucket(bucketName, properties.getRegion());
+ } catch (Exception e) {
+ throw new OssException("创建Bucket失败, 请核对七牛云配置信息:[" + e.getMessage() + "]");
+ }
+ }
+
+ @Override
+ public OssEnumd getServiceType() {
+ return OssEnumd.QINIU;
+ }
+
+ @Override
+ public UploadResult upload(byte[] data, String path, String contentType) {
+ try {
+ String token = auth.uploadToken(properties.getBucketName());
+ Response res = uploadManager.put(data, path, token, null, contentType, false);
+ if (!res.isOK()) {
+ throw new RuntimeException("上传七牛出错:" + res.error);
+ }
+ } catch (Exception e) {
+ throw new OssException("上传文件失败,请核对七牛配置信息:[" + e.getMessage() + "]");
+ }
+ return UploadResult.builder().url(getEndpointLink() + "/" + path).filename(path).build();
+ }
+
+ @Override
+ public void delete(String path) {
+ try {
+ path = path.replace(getEndpointLink() + "/", "");
+ Response res = bucketManager.delete(properties.getBucketName(), path);
+ if (!res.isOK()) {
+ throw new RuntimeException("删除七牛文件出错:" + res.error);
+ }
+ } catch (Exception e) {
+ throw new OssException(e.getMessage());
+ }
+ }
+
+ @Override
+ public UploadResult uploadSuffix(byte[] data, String suffix, String contentType) {
+ return upload(data, getPath(properties.getPrefix(), suffix), contentType);
+ }
+
+ @Override
+ public UploadResult uploadSuffix(InputStream inputStream, String suffix, String contentType) {
+ return upload(inputStream, getPath(properties.getPrefix(), suffix), contentType);
+ }
+
+ @Override
+ public String getEndpointLink() {
+ return properties.getEndpoint();
+ }
+
+ private Region getRegion(String region) {
+ switch (region) {
+ case "z0":
+ return Region.region0();
+ case "z1":
+ return Region.region1();
+ case "z2":
+ return Region.region2();
+ case "na0":
+ return Region.regionNa0();
+ case "as0":
+ return Region.regionAs0();
+ default:
+ return Region.autoRegion();
+ }
+ }
+
+}
diff --git a/ruoyi-common/ruoyi-common-oss/src/main/resources/META-INF/spring.factories b/ruoyi-common/ruoyi-common-oss/src/main/resources/META-INF/spring.factories
new file mode 100644
index 00000000..485802b1
--- /dev/null
+++ b/ruoyi-common/ruoyi-common-oss/src/main/resources/META-INF/spring.factories
@@ -0,0 +1 @@
+org.springframework.boot.autoconfigure.EnableAutoConfiguration=
\ No newline at end of file