Jelajahi Sumber

add 增加 ruoyi-common-oss 模块

疯狂的狮子li 4 tahun lalu
induk
melakukan
7c5b144b90
18 mengubah file dengan 1057 tambahan dan 0 penghapusan
  1. 6 0
      pom.xml
  2. 1 0
      ruoyi-common/pom.xml
  3. 7 0
      ruoyi-common/ruoyi-common-bom/pom.xml
  4. 53 0
      ruoyi-common/ruoyi-common-oss/pom.xml
  5. 38 0
      ruoyi-common/ruoyi-common-oss/src/main/java/com/ruoyi/common/oss/constant/OssConstant.java
  6. 24 0
      ruoyi-common/ruoyi-common-oss/src/main/java/com/ruoyi/common/oss/entity/UploadResult.java
  7. 52 0
      ruoyi-common/ruoyi-common-oss/src/main/java/com/ruoyi/common/oss/enumd/OssEnumd.java
  8. 51 0
      ruoyi-common/ruoyi-common-oss/src/main/java/com/ruoyi/common/oss/enumd/PolicyType.java
  9. 16 0
      ruoyi-common/ruoyi-common-oss/src/main/java/com/ruoyi/common/oss/exception/OssException.java
  10. 79 0
      ruoyi-common/ruoyi-common-oss/src/main/java/com/ruoyi/common/oss/factory/OssFactory.java
  11. 48 0
      ruoyi-common/ruoyi-common-oss/src/main/java/com/ruoyi/common/oss/properties/OssProperties.java
  12. 67 0
      ruoyi-common/ruoyi-common-oss/src/main/java/com/ruoyi/common/oss/service/IOssStrategy.java
  13. 64 0
      ruoyi-common/ruoyi-common-oss/src/main/java/com/ruoyi/common/oss/service/abstractd/AbstractOssStrategy.java
  14. 115 0
      ruoyi-common/ruoyi-common-oss/src/main/java/com/ruoyi/common/oss/service/impl/AliyunOssStrategy.java
  15. 184 0
      ruoyi-common/ruoyi-common-oss/src/main/java/com/ruoyi/common/oss/service/impl/MinioOssStrategy.java
  16. 124 0
      ruoyi-common/ruoyi-common-oss/src/main/java/com/ruoyi/common/oss/service/impl/QcloudOssStrategy.java
  17. 127 0
      ruoyi-common/ruoyi-common-oss/src/main/java/com/ruoyi/common/oss/service/impl/QiniuOssStrategy.java
  18. 1 0
      ruoyi-common/ruoyi-common-oss/src/main/resources/META-INF/spring.factories

+ 6 - 0
pom.xml

@@ -49,6 +49,12 @@
         <knife4j.version>3.0.3</knife4j.version>
         <satoken.version>1.28.0</satoken.version>
 
+        <!-- OSS 配置 -->
+        <qiniu.version>7.9.2</qiniu.version>
+        <aliyun.oss.version>3.14.0</aliyun.oss.version>
+        <qcloud.cos.version>5.6.68</qcloud.cos.version>
+        <minio.version>8.3.5</minio.version>
+
         <!-- docker 配置 -->
         <docker.registry.url>localhost</docker.registry.url>
         <docker.registry.host>http://${docker.registry.url}:2375</docker.registry.host>

+ 1 - 0
ruoyi-common/pom.xml

@@ -25,6 +25,7 @@
         <module>ruoyi-common-dubbo</module>
         <module>ruoyi-common-seata</module>
         <module>ruoyi-common-loadbalancer</module>
+        <module>ruoyi-common-oss</module>
     </modules>
 
     <artifactId>ruoyi-common</artifactId>

+ 7 - 0
ruoyi-common/ruoyi-common-bom/pom.xml

@@ -114,6 +114,13 @@
                 <artifactId>ruoyi-common-loadbalancer</artifactId>
                 <version>${project.version}</version>
             </dependency>
+
+            <dependency>
+                <groupId>com.ruoyi</groupId>
+                <artifactId>ruoyi-common-oss</artifactId>
+                <version>${project.version}</version>
+            </dependency>
+
         </dependencies>
     </dependencyManagement>
 </project>

+ 53 - 0
ruoyi-common/ruoyi-common-oss/pom.xml

@@ -0,0 +1,53 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xmlns="http://maven.apache.org/POM/4.0.0"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <parent>
+        <groupId>com.ruoyi</groupId>
+        <artifactId>ruoyi-common</artifactId>
+        <version>0.5.0</version>
+    </parent>
+    <modelVersion>4.0.0</modelVersion>
+
+    <artifactId>ruoyi-common-oss</artifactId>
+
+    <description>
+        ruoyi-common-oss oss服务
+    </description>
+
+	<dependencies>
+
+        <dependency>
+            <groupId>com.ruoyi</groupId>
+            <artifactId>ruoyi-common-redis</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>com.qiniu</groupId>
+            <artifactId>qiniu-java-sdk</artifactId>
+            <version>${qiniu.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>com.aliyun.oss</groupId>
+            <artifactId>aliyun-sdk-oss</artifactId>
+            <version>${aliyun.oss.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>com.qcloud</groupId>
+            <artifactId>cos_api</artifactId>
+            <version>${qcloud.cos.version}</version>
+            <exclusions>
+                <exclusion>
+                    <groupId>org.slf4j</groupId>
+                    <artifactId>slf4j-log4j12</artifactId>
+                </exclusion>
+            </exclusions>
+        </dependency>
+        <dependency>
+            <groupId>io.minio</groupId>
+            <artifactId>minio</artifactId>
+            <version>${minio.version}</version>
+        </dependency>
+
+    </dependencies>
+</project>

+ 38 - 0
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<Integer> SYSTEM_DATA_IDS = Arrays.asList(1, 2, 3, 4);
+
+}

+ 24 - 0
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;
+}

+ 52 - 0
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;
+    }
+
+}

+ 51 - 0
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;
+
+}

+ 16 - 0
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);
+    }
+
+}

+ 79 - 0
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());
+    }
+
+}

+ 48 - 0
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;
+
+}

+ 67 - 0
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);
+
+}

+ 64 - 0
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();
+}

+ 115 - 0
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();
+    }
+}

+ 184 - 0
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();
+    }
+}

+ 124 - 0
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();
+    }
+}

+ 127 - 0
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();
+        }
+    }
+
+}

+ 1 - 0
ruoyi-common/ruoyi-common-oss/src/main/resources/META-INF/spring.factories

@@ -0,0 +1 @@
+org.springframework.boot.autoconfigure.EnableAutoConfiguration=