mirror of
https://gitee.com/dromara/RuoYi-Cloud-Plus.git
synced 2025-09-05 20:08:05 +00:00
add 增加 ruoyi-common-oss 模块
This commit is contained in:
6
pom.xml
6
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>
|
||||
|
@@ -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>
|
||||
|
@@ -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
ruoyi-common/ruoyi-common-oss/pom.xml
Normal file
53
ruoyi-common/ruoyi-common-oss/pom.xml
Normal file
@@ -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>
|
@@ -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);
|
||||
|
||||
}
|
@@ -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;
|
||||
}
|
@@ -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;
|
||||
}
|
||||
|
||||
}
|
@@ -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;
|
||||
|
||||
}
|
@@ -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);
|
||||
}
|
||||
|
||||
}
|
@@ -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());
|
||||
}
|
||||
|
||||
}
|
@@ -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;
|
||||
|
||||
}
|
@@ -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);
|
||||
|
||||
}
|
@@ -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();
|
||||
}
|
@@ -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();
|
||||
}
|
||||
}
|
@@ -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();
|
||||
}
|
||||
}
|
@@ -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();
|
||||
}
|
||||
}
|
@@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1 @@
|
||||
org.springframework.boot.autoconfigure.EnableAutoConfiguration=
|
Reference in New Issue
Block a user