diff --git a/pom.xml b/pom.xml
index 9d30b500d..109605559 100644
--- a/pom.xml
+++ b/pom.xml
@@ -37,6 +37,8 @@
1.2.13
5.7.12
5.3.39
+
+ 3.17.4
@@ -233,6 +235,12 @@
${hutool.version}
+
+ com.aliyun.oss
+ aliyun-sdk-oss
+ ${aliyun-sdk-oss.version}
+
+
diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/common/CommonController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/common/CommonController.java
index d51d61d00..90eb62a95 100644
--- a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/common/CommonController.java
+++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/common/CommonController.java
@@ -1,163 +1,47 @@
package com.ruoyi.web.controller.common;
-import java.util.ArrayList;
-import java.util.List;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
+import com.aliyun.oss.common.auth.Credentials;
+import com.ruoyi.common.core.domain.R;
+import com.ruoyi.framework.config.properties.OSSProperties;
+import com.ruoyi.framework.oss.OSSClientWrapper;
+import com.ruoyi.web.controller.common.vo.STSCredentialsVO;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.GetMapping;
-import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
-import org.springframework.web.multipart.MultipartFile;
-import com.ruoyi.common.config.RuoYiConfig;
-import com.ruoyi.common.constant.Constants;
-import com.ruoyi.common.core.domain.AjaxResult;
-import com.ruoyi.common.utils.StringUtils;
-import com.ruoyi.common.utils.file.FileUploadUtils;
-import com.ruoyi.common.utils.file.FileUtils;
-import com.ruoyi.framework.config.ServerConfig;
/**
* 通用请求处理
- *
+ *
* @author ruoyi
*/
+@Api(tags = "通用")
+@Slf4j
@RestController
@RequestMapping("/common")
-public class CommonController
-{
- private static final Logger log = LoggerFactory.getLogger(CommonController.class);
-
+public class CommonController {
@Autowired
- private ServerConfig serverConfig;
+ private OSSClientWrapper ossClient;
+ @Autowired
+ private OSSProperties ossProperties;
- private static final String FILE_DELIMETER = ",";
-
- /**
- * 通用下载请求
- *
- * @param fileName 文件名称
- * @param delete 是否删除
- */
- @GetMapping("/download")
- public void fileDownload(String fileName, Boolean delete, HttpServletResponse response, HttpServletRequest request)
- {
- try
- {
- if (!FileUtils.checkAllowDownload(fileName))
- {
- throw new Exception(StringUtils.format("文件名称({})非法,不允许下载。 ", fileName));
- }
- String realFileName = System.currentTimeMillis() + fileName.substring(fileName.indexOf("_") + 1);
- String filePath = RuoYiConfig.getDownloadPath() + fileName;
-
- response.setContentType(MediaType.APPLICATION_OCTET_STREAM_VALUE);
- FileUtils.setAttachmentResponseHeader(response, realFileName);
- FileUtils.writeBytes(filePath, response.getOutputStream());
- if (delete)
- {
- FileUtils.deleteFile(filePath);
- }
- }
- catch (Exception e)
- {
- log.error("下载文件失败", e);
- }
+ @ApiOperation("获取OSS临时访问凭证")
+ @GetMapping("/getCredentials")
+ public R getCredentials() {
+ STSCredentialsVO vo = new STSCredentialsVO();
+ Credentials credentials = ossClient.createStsCredentials();
+ vo.setAccessKeyId(credentials.getAccessKeyId());
+ vo.setAccessKeySecret(credentials.getSecretAccessKey());
+ vo.setSecurityToken(credentials.getSecurityToken());
+ vo.setBucketName(ossProperties.getBucketName());
+ vo.setRegionId(ossProperties.getRegionId());
+ vo.setEndPoint(ossProperties.getEndPoint());
+ vo.setExpiredDuration(ossProperties.getExpiredDuration());
+ vo.setHttpsFlag(ossProperties.isHttps());
+ return R.ok(vo);
}
- /**
- * 通用上传请求(单个)
- */
- @PostMapping("/upload")
- public AjaxResult uploadFile(MultipartFile file) throws Exception
- {
- try
- {
- // 上传文件路径
- String filePath = RuoYiConfig.getUploadPath();
- // 上传并返回新文件名称
- String fileName = FileUploadUtils.upload(filePath, file);
- String url = serverConfig.getUrl() + fileName;
- AjaxResult ajax = AjaxResult.success();
- ajax.put("url", url);
- ajax.put("fileName", fileName);
- ajax.put("newFileName", FileUtils.getName(fileName));
- ajax.put("originalFilename", file.getOriginalFilename());
- return ajax;
- }
- catch (Exception e)
- {
- return AjaxResult.error(e.getMessage());
- }
- }
-
- /**
- * 通用上传请求(多个)
- */
- @PostMapping("/uploads")
- public AjaxResult uploadFiles(List files) throws Exception
- {
- try
- {
- // 上传文件路径
- String filePath = RuoYiConfig.getUploadPath();
- List urls = new ArrayList();
- List fileNames = new ArrayList();
- List newFileNames = new ArrayList();
- List originalFilenames = new ArrayList();
- for (MultipartFile file : files)
- {
- // 上传并返回新文件名称
- String fileName = FileUploadUtils.upload(filePath, file);
- String url = serverConfig.getUrl() + fileName;
- urls.add(url);
- fileNames.add(fileName);
- newFileNames.add(FileUtils.getName(fileName));
- originalFilenames.add(file.getOriginalFilename());
- }
- AjaxResult ajax = AjaxResult.success();
- ajax.put("urls", StringUtils.join(urls, FILE_DELIMETER));
- ajax.put("fileNames", StringUtils.join(fileNames, FILE_DELIMETER));
- ajax.put("newFileNames", StringUtils.join(newFileNames, FILE_DELIMETER));
- ajax.put("originalFilenames", StringUtils.join(originalFilenames, FILE_DELIMETER));
- return ajax;
- }
- catch (Exception e)
- {
- return AjaxResult.error(e.getMessage());
- }
- }
-
- /**
- * 本地资源通用下载
- */
- @GetMapping("/download/resource")
- public void resourceDownload(String resource, HttpServletRequest request, HttpServletResponse response)
- throws Exception
- {
- try
- {
- if (!FileUtils.checkAllowDownload(resource))
- {
- throw new Exception(StringUtils.format("资源文件({})非法,不允许下载。 ", resource));
- }
- // 本地资源路径
- String localPath = RuoYiConfig.getProfile();
- // 数据库资源地址
- String downloadPath = localPath + StringUtils.substringAfter(resource, Constants.RESOURCE_PREFIX);
- // 下载名称
- String downloadName = StringUtils.substringAfterLast(downloadPath, "/");
- response.setContentType(MediaType.APPLICATION_OCTET_STREAM_VALUE);
- FileUtils.setAttachmentResponseHeader(response, downloadName);
- FileUtils.writeBytes(downloadPath, response.getOutputStream());
- }
- catch (Exception e)
- {
- log.error("下载文件失败", e);
- }
- }
}
diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/common/vo/STSCredentialsVO.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/common/vo/STSCredentialsVO.java
new file mode 100644
index 000000000..9973db697
--- /dev/null
+++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/common/vo/STSCredentialsVO.java
@@ -0,0 +1,58 @@
+package com.ruoyi.web.controller.common.vo;
+
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Getter;
+import lombok.Setter;
+import lombok.ToString;
+
+/**
+ * @author liangyuqi
+ * @date 2021/11/15 14:36
+ */
+@ApiModel
+@Getter
+@Setter
+@ToString
+public class STSCredentialsVO {
+ /**
+ * ID
+ */
+ @ApiModelProperty("ID")
+ private String accessKeyId;
+ /**
+ * Secret
+ */
+ @ApiModelProperty("Secret")
+ private String accessKeySecret;
+ /**
+ * token
+ */
+ @ApiModelProperty("token")
+ private String securityToken;
+ /**
+ * 有效时长
+ */
+ @ApiModelProperty("凭证的有效时长,单位秒")
+ private Long expiredDuration;
+ /**
+ * regionId
+ */
+ @ApiModelProperty("regionId")
+ private String regionId;
+ /**
+ * endPoint
+ */
+ @ApiModelProperty("endPoint")
+ private String endPoint;
+ /**
+ * 桶
+ */
+ @ApiModelProperty("bucketName")
+ private String bucketName;
+ /**
+ * https标记
+ */
+ @ApiModelProperty("https标记")
+ private Boolean httpsFlag;
+}
diff --git a/ruoyi-admin/src/main/resources/application.yml b/ruoyi-admin/src/main/resources/application.yml
index 090703a1e..4c7389d0c 100644
--- a/ruoyi-admin/src/main/resources/application.yml
+++ b/ruoyi-admin/src/main/resources/application.yml
@@ -12,6 +12,15 @@ ruoyi:
addressEnabled: false
# 验证码类型 math 数字计算 char 字符验证
captchaType: math
+oss:
+ endPoint: oss-cn-beijing.aliyuncs.com
+ accessKeyId: LTAI5tFXTfY5Rsiwvrg9gUuk
+ accessKeySecret: Ebbj7anXSdbJwfm5zbTfHkJ5QWDbTP
+ bucketName: lyq-private
+ https: true
+ regionId: cn-beijing
+ roleArn: acs:ram::1919425406190533:role/sts-role
+ expiredDuration: 3600
# 开发环境配置
server:
diff --git a/ruoyi-common/pom.xml b/ruoyi-common/pom.xml
index 65cc54adc..87a79d9d6 100644
--- a/ruoyi-common/pom.xml
+++ b/ruoyi-common/pom.xml
@@ -19,7 +19,6 @@
org.projectlombok
lombok
- provided
@@ -27,6 +26,12 @@
hutool-all
+
+
+ com.aliyun.oss
+ aliyun-sdk-oss
+
+
com.baomidou
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/R.java b/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/R.java
index ef15802b9..29a4e0b31 100644
--- a/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/R.java
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/R.java
@@ -2,12 +2,14 @@ package com.ruoyi.common.core.domain;
import java.io.Serializable;
import com.ruoyi.common.constant.HttpStatus;
+import lombok.ToString;
/**
* 响应信息主体
*
* @author ruoyi
*/
+@ToString
public class R implements Serializable
{
private static final long serialVersionUID = 1L;
diff --git a/ruoyi-framework/src/main/java/com/ruoyi/framework/config/OSSAutoConfiguration.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/config/OSSAutoConfiguration.java
new file mode 100644
index 000000000..76f95138e
--- /dev/null
+++ b/ruoyi-framework/src/main/java/com/ruoyi/framework/config/OSSAutoConfiguration.java
@@ -0,0 +1,42 @@
+package com.ruoyi.framework.config;
+
+import com.ruoyi.framework.config.properties.OSSProperties;
+import com.ruoyi.framework.oss.OSSClientWrapper;
+import com.ruoyi.framework.oss.OSSConfiguration;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
+import org.springframework.boot.context.properties.EnableConfigurationProperties;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+/**
+ * @author liangyq
+ * @date 2025-03-24
+ */
+@Configuration
+@ConditionalOnClass(OSSClientWrapper.class)
+@ConditionalOnProperty({"oss.accessKeyId", "oss.accessKeySecret", "oss.endPoint", "oss.bucketName"})
+@EnableConfigurationProperties(OSSProperties.class)
+public class OSSAutoConfiguration {
+
+ @Bean
+ @ConditionalOnMissingBean
+ public OSSClientWrapper ossClient(OSSProperties properties) {
+ OSSConfiguration ossConfiguration = toOSSConfiguration(properties);
+ return new OSSClientWrapper(ossConfiguration);
+ }
+
+ private OSSConfiguration toOSSConfiguration(OSSProperties properties) {
+ OSSConfiguration configuration = new OSSConfiguration();
+ configuration.setEndpoint(properties.getEndPoint());
+ configuration.setAccessKeyId(properties.getAccessKeyId());
+ configuration.setAccessKeySecret(properties.getAccessKeySecret());
+ configuration.setBucketName(properties.getBucketName());
+ configuration.setRegionId(properties.getRegionId());
+ configuration.setRoleArn(properties.getRoleArn());
+ configuration.setHttps(properties.isHttps());
+ configuration.setExpiredDuration(properties.getExpiredDuration());
+ return configuration;
+ }
+}
diff --git a/ruoyi-framework/src/main/java/com/ruoyi/framework/config/properties/OSSProperties.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/config/properties/OSSProperties.java
new file mode 100644
index 000000000..a8a5e226f
--- /dev/null
+++ b/ruoyi-framework/src/main/java/com/ruoyi/framework/config/properties/OSSProperties.java
@@ -0,0 +1,29 @@
+package com.ruoyi.framework.config.properties;
+
+import lombok.Data;
+import org.springframework.boot.context.properties.ConfigurationProperties;
+
+/**
+ * @author liangyq
+ * @date 2025-03-24
+ */
+@Data
+@ConfigurationProperties(prefix = "oss")
+public class OSSProperties {
+
+ private String endPoint;
+
+ private String accessKeyId;
+
+ private String accessKeySecret;
+
+ private String bucketName;
+
+ private boolean https;
+
+ private String regionId;
+
+ private String roleArn;
+
+ private Long expiredDuration;
+}
diff --git a/ruoyi-framework/src/main/java/com/ruoyi/framework/oss/OSSClientWrapper.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/oss/OSSClientWrapper.java
new file mode 100644
index 000000000..ff45504d7
--- /dev/null
+++ b/ruoyi-framework/src/main/java/com/ruoyi/framework/oss/OSSClientWrapper.java
@@ -0,0 +1,301 @@
+package com.ruoyi.framework.oss;
+
+import com.aliyun.oss.*;
+import com.aliyun.oss.common.auth.Credentials;
+import com.aliyun.oss.common.auth.CredentialsProviderFactory;
+import com.aliyun.oss.common.auth.STSAssumeRoleSessionCredentialsProvider;
+import com.aliyun.oss.common.comm.Protocol;
+import com.aliyun.oss.model.*;
+import io.jsonwebtoken.lang.Assert;
+import lombok.extern.slf4j.Slf4j;
+
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.InputStream;
+import java.net.URL;
+import java.util.Base64;
+import java.util.Date;
+
+/**
+ * @author liangyq
+ * @date 2025-03-24
+ */
+@Slf4j
+public class OSSClientWrapper {
+
+ private final OSS client;
+
+ private final OSSConfiguration configuration;
+
+ public OSSClientWrapper(OSSConfiguration configuration) {
+ this.configuration = configuration;
+ ClientBuilderConfiguration config = getClientBuilderConfiguration();
+ client = new OSSClientBuilder().build(configuration.getEndpoint(), configuration.getAccessKeyId(), configuration.getAccessKeySecret(), config);
+ }
+
+ public OSSClientWrapper(STSAssumeRoleSessionCredentialsProvider credentialsProvider, OSSConfiguration configuration) {
+ this.configuration = configuration;
+ ClientBuilderConfiguration config = getClientBuilderConfiguration();
+ client = new OSSClientBuilder().build(configuration.getEndpoint(), credentialsProvider, config);
+ }
+
+ /**
+ * 创建临时访问客户端
+ * 临时访问客户端过期时间通过OSSConfiguration#expiredDuration配置
+ *
+ * @return 临时访问客户端
+ */
+ public OSSClientWrapper createSTSClient() {
+ STSAssumeRoleSessionCredentialsProvider credentialsProvider = this.createSTSCredentialsProvider();
+ Credentials credentials = credentialsProvider.getCredentials();
+ OSSConfiguration newOSSConfiguration = this.configuration.clone();
+ newOSSConfiguration.setAccessKeyId(credentials.getAccessKeyId());
+ newOSSConfiguration.setAccessKeySecret(credentials.getSecretAccessKey());
+ return new OSSClientWrapper(credentialsProvider, newOSSConfiguration);
+ }
+
+ /**
+ * 创建临时访问key值 一般用于给前端提供领时上传功能
+ * 临时访问客户端过期时间通过OSSConfiguration#expiredDuration配置
+ *
+ * @return 临时访问key
+ */
+ public Credentials createStsCredentials() {
+ return this.createSTSCredentialsProvider().getCredentials();
+ }
+
+ /**
+ * 文件上传
+ *
+ * @param key key
+ * @param inputStream 文件流
+ */
+ public void upload(String key, InputStream inputStream)
+ throws Exception {
+ upload(key, inputStream, null);
+ }
+
+ /**
+ * 文件上传
+ *
+ * @param key key
+ * @param inputStream 文件流
+ * @param contentType 文件类型
+ */
+ public void upload(String key, InputStream inputStream, String contentType)
+ throws Exception {
+ upload(key, inputStream, contentType, null);
+ }
+
+ /**
+ * 文件上传
+ *
+ * @param key key
+ * @param inputStream 文件流
+ * @param contentType 文件类型
+ * @param contentDisposition 下载描述信息
+ */
+ public void upload(String key, InputStream inputStream, String contentType, String contentDisposition) throws Exception {
+ ObjectMetadata objectMeta = new ObjectMetadata();
+ objectMeta.setContentLength(inputStream.available());
+ // 可以在metadata中标记文件类型
+ if (contentType == null) {
+// contentType = deduceContentType(key);
+ }
+ objectMeta.setContentType(contentType);
+ // 设置下载名
+ objectMeta.setContentDisposition(contentDisposition);
+ client.putObject(configuration.getBucketName(), key, inputStream, objectMeta);
+ if (!client.doesObjectExist(configuration.getBucketName(), key)) {
+ throw new IllegalStateException("文件上传失败");
+ }
+ }
+
+ /**
+ * 移动文件
+ *
+ * @param sourceKey 源KEY
+ * @param targetKey 目标KEY
+ */
+ public void move(String sourceKey, String targetKey) {
+ if (!client.doesObjectExist(configuration.getBucketName(), sourceKey)) {
+ throw new IllegalStateException("源文件信息不存在");
+ }
+ client.copyObject(configuration.getBucketName(), sourceKey, configuration.getBucketName(), targetKey);
+ if (!client.doesObjectExist(configuration.getBucketName(), targetKey)) {
+ throw new IllegalStateException("移动文件失败[1]");
+ }
+ if (!this.delete(sourceKey)) {
+ throw new IllegalStateException("移动文件失败[2]");
+ }
+ }
+
+ /**
+ * 根据key,获取访问路径
+ *
+ * @param key key(文件相对路径)
+ * @param expireTime 过期时间,单位毫秒
+ */
+ public URL generateUrl(String key, Long expireTime) throws Exception {
+ return generateUrl(key, expireTime, false);
+ }
+
+ /**
+ * 根据key,获取访问路径
+ *
+ * @param key key(文件相对路径)
+ * @param expireTime 过期时间,单位毫秒
+ * @param down 是否生成直接下载的url
+ */
+ public URL generateUrl(String key, Long expireTime, boolean down) throws Exception {
+ Assert.notNull(expireTime, "过期时间为空");
+ GeneratePresignedUrlRequest request;
+ Date expiration = new Date(System.currentTimeMillis() + expireTime);
+ request = new GeneratePresignedUrlRequest(this.configuration.getBucketName(), key);
+ request.setExpiration(expiration);
+ request.setMethod(HttpMethod.GET);
+ ResponseHeaderOverrides header = new ResponseHeaderOverrides();
+// header.setContentType(this.deduceContentType(key));
+ if (down) {
+ //设置响应头强制下载
+ header.setContentDisposition("attachment;");
+ }
+ request.setResponseHeaders(header);
+ return this.client.generatePresignedUrl(request);
+ }
+
+ public String generateBase64(String key) {
+ if (key == null) {
+ return null;
+ }
+ try {
+ OSSObject ossObject = this.client.getObject(this.configuration.getBucketName(), key);
+ if (ossObject == null) {
+ return null;
+ }
+ InputStream inputStream = ossObject.getObjectContent();
+ ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
+ byte[] data = new byte[1024];
+ int length;
+ while ((length = inputStream.read(data)) != -1) {
+ outputStream.write(data, 0, length);
+ }
+ outputStream.close();
+ String base64 = Base64.getEncoder().encodeToString(outputStream.toByteArray());
+ return String.format("data:image/png;base64,%s", base64);
+ } catch (Exception e) {
+ log.error("generateBase64", e);
+ }
+ return null;
+ }
+
+ private String deduceContentType(String key) {
+ int index = key.lastIndexOf(".");
+ String fileExtension = null;
+ if (index != -1) {
+ fileExtension = key.substring(index);
+ }
+ //文件的后缀名
+ if (".bmp".equalsIgnoreCase(fileExtension)) {
+ return "image/bmp";
+ }
+ if (".gif".equalsIgnoreCase(fileExtension)) {
+ return "image/gif";
+ }
+ if (".jpeg".equalsIgnoreCase(fileExtension)) {
+ return "image/jpeg";
+ }
+ if (".jpg".equalsIgnoreCase(fileExtension)) {
+ return "image/jpg";
+ }
+ if (".png".equalsIgnoreCase(fileExtension)) {
+ return "image/png";
+ }
+ if (".html".equalsIgnoreCase(fileExtension)) {
+ return "text/html";
+ }
+ if (".txt".equalsIgnoreCase(fileExtension)) {
+ return "text/plain";
+ }
+ if (".vsd".equalsIgnoreCase(fileExtension)) {
+ return "application/vnd.visio";
+ }
+ if (".ppt".equalsIgnoreCase(fileExtension) || ".pptx".equalsIgnoreCase(fileExtension)) {
+ return "application/vnd.ms-powerpoint";
+ }
+ if (".doc".equalsIgnoreCase(fileExtension) || ".docx".equalsIgnoreCase(fileExtension)) {
+ return "application/msword";
+ }
+ if (".xml".equalsIgnoreCase(fileExtension)) {
+ return "text/xml";
+ }
+ if (".zip".equalsIgnoreCase(fileExtension)) {
+ return "application/zip";
+ }
+ if (".pdf".equalsIgnoreCase(fileExtension)) {
+ return "application/pdf";
+ }
+ if (".xls".equalsIgnoreCase(fileExtension) || ".xlsx".equalsIgnoreCase(fileExtension)) {
+ return "application/vnd.ms-excel";
+ }
+ //默认返回类型
+ return "image/jpeg";
+ }
+
+ public InputStream getObject(String key) throws Exception {
+ OSSObject ossObject = client.getObject(configuration.getBucketName(), key);
+ return ossObject.getObjectContent();
+ }
+
+ /**
+ * 下载文件
+ */
+ public void download(OSSClient client, String key, String filename)
+ throws OSSException, ClientException {
+ client.getObject(new GetObjectRequest(configuration.getBucketName(), key), new File(filename));
+ }
+
+ /**
+ * 删除oss上的文件
+ *
+ * @return 成功删除返回true 不存在返回false
+ */
+ public boolean delete(String key) {
+ //检查是否是有效文件
+ boolean exists = client.doesObjectExist(configuration.getBucketName(), key);
+ if (exists) {
+ client.deleteObject(configuration.getBucketName(), key);
+ }
+ return exists;
+ }
+
+ public OSS getOriginalClient() {
+ return client;
+ }
+
+ private ClientBuilderConfiguration getClientBuilderConfiguration() {
+ ClientBuilderConfiguration config = new ClientBuilderConfiguration();
+ config.setProtocol(configuration.isHttps() ? Protocol.HTTPS : Protocol.HTTP);
+ return config;
+ }
+
+ private STSAssumeRoleSessionCredentialsProvider createSTSCredentialsProvider() {
+ try {
+ return CredentialsProviderFactory.newSTSAssumeRoleSessionCredentialsProvider(
+ configuration.getRegionId(),
+ configuration.getAccessKeyId(),
+ configuration.getAccessKeySecret(),
+ configuration.getRoleArn()
+ )
+ .withExpiredDuration(configuration.getExpiredDuration());
+ } catch (com.aliyuncs.exceptions.ClientException e) {
+ log.error("createStsCredentialsProvider ERROR", e);
+ throw new RuntimeException("create createStsCredentialsProvider error");
+ }
+ }
+
+ public OSSConfiguration getConfiguration() {
+ return this.configuration;
+ }
+
+}
diff --git a/ruoyi-framework/src/main/java/com/ruoyi/framework/oss/OSSConfiguration.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/oss/OSSConfiguration.java
new file mode 100644
index 000000000..eca66df14
--- /dev/null
+++ b/ruoyi-framework/src/main/java/com/ruoyi/framework/oss/OSSConfiguration.java
@@ -0,0 +1,33 @@
+package com.ruoyi.framework.oss;
+
+import lombok.Data;
+
+/**
+ * @author liangyq
+ * @date 2025-03-24
+ */
+@Data
+public class OSSConfiguration {
+ private String endpoint;
+ private String accessKeyId;
+ private String accessKeySecret;
+ private String bucketName;
+ private String regionId;
+ private String roleArn;
+ private boolean https;
+ private Long expiredDuration;
+
+ @Override
+ public OSSConfiguration clone() {
+ OSSConfiguration configuration = new OSSConfiguration();
+ configuration.setEndpoint(this.endpoint);
+ configuration.setAccessKeyId(this.accessKeyId);
+ configuration.setAccessKeySecret(this.getAccessKeySecret());
+ configuration.setBucketName(this.bucketName);
+ configuration.setRegionId(this.regionId);
+ configuration.setRoleArn(this.roleArn);
+ configuration.setHttps(this.https);
+ configuration.setExpiredDuration(this.expiredDuration);
+ return configuration;
+ }
+}
diff --git a/ruoyi-system/pom.xml b/ruoyi-system/pom.xml
index 35a851822..196529397 100644
--- a/ruoyi-system/pom.xml
+++ b/ruoyi-system/pom.xml
@@ -17,12 +17,6 @@
-
- org.projectlombok
- lombok
- provided
-
-
com.ruoyi