feat(storage): 集成MinIO对象存储支持

- 添加MinIO配置属性类MinioProperties
- 实现MinIO文件上传服务MinioService
- 在CommonController中增加MinIO上传逻辑分支
- 支持单文件和多文件的MinIO上传处理
- 保留原有本地文件上传作为备选方案- 添加MinIO Java SDK依赖到框架模块
- 移除重复的Spring Context依赖声明
This commit is contained in:
2025-09-28 18:23:21 +08:00
parent 8b3e41f60f
commit f3e072352b
7 changed files with 191 additions and 16 deletions

View File

@@ -62,10 +62,6 @@
<groupId>org.springframework</groupId> <groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId> <artifactId>spring-context</artifactId>
</dependency> </dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
</dependency>
</dependencies> </dependencies>

View File

@@ -20,6 +20,8 @@ import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.file.FileUploadUtils; import com.ruoyi.common.utils.file.FileUploadUtils;
import com.ruoyi.common.utils.file.FileUtils; import com.ruoyi.common.utils.file.FileUtils;
import com.ruoyi.framework.config.ServerConfig; import com.ruoyi.framework.config.ServerConfig;
import com.ruoyi.framework.config.MinioProperties;
import com.ruoyi.framework.service.MinioService;
/** /**
* 通用请求处理 * 通用请求处理
@@ -35,6 +37,12 @@ public class CommonController
@Autowired @Autowired
private ServerConfig serverConfig; private ServerConfig serverConfig;
@Autowired(required = false)
private MinioService minioService;
@Autowired(required = false)
private MinioProperties minioProperties;
private static final String FILE_DELIMETER = ","; private static final String FILE_DELIMETER = ",";
/** /**
@@ -77,9 +85,22 @@ public class CommonController
{ {
try try
{ {
// 上传文件路径 if (minioProperties != null && minioProperties.isEnabled())
{
MinioService.UploadResult result = minioService.upload(file);
String fileName = result.getObjectName();
String url = result.getUrl();
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;
}
// 本地上传路径
String filePath = RuoYiConfig.getUploadPath(); String filePath = RuoYiConfig.getUploadPath();
// 上传并返回新文件名称 // 本地上传并返回新文件名称
String fileName = FileUploadUtils.upload(filePath, file); String fileName = FileUploadUtils.upload(filePath, file);
String url = serverConfig.getUrl() + fileName; String url = serverConfig.getUrl() + fileName;
AjaxResult ajax = AjaxResult.success(); AjaxResult ajax = AjaxResult.success();
@@ -103,21 +124,37 @@ public class CommonController
{ {
try try
{ {
// 上传文件路径
String filePath = RuoYiConfig.getUploadPath();
List<String> urls = new ArrayList<String>(); List<String> urls = new ArrayList<String>();
List<String> fileNames = new ArrayList<String>(); List<String> fileNames = new ArrayList<String>();
List<String> newFileNames = new ArrayList<String>(); List<String> newFileNames = new ArrayList<String>();
List<String> originalFilenames = new ArrayList<String>(); List<String> originalFilenames = new ArrayList<String>();
for (MultipartFile file : files) if (minioProperties != null && minioProperties.isEnabled())
{ {
// 上传并返回新文件名称 for (MultipartFile file : files)
String fileName = FileUploadUtils.upload(filePath, file); {
String url = serverConfig.getUrl() + fileName; MinioService.UploadResult result = minioService.upload(file);
urls.add(url); String fileName = result.getObjectName();
fileNames.add(fileName); String url = result.getUrl();
newFileNames.add(FileUtils.getName(fileName)); urls.add(url);
originalFilenames.add(file.getOriginalFilename()); fileNames.add(fileName);
newFileNames.add(FileUtils.getName(fileName));
originalFilenames.add(file.getOriginalFilename());
}
}
else
{
// 本地上传路径
String filePath = RuoYiConfig.getUploadPath();
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(); AjaxResult ajax = AjaxResult.success();
ajax.put("urls", StringUtils.join(urls, FILE_DELIMETER)); ajax.put("urls", StringUtils.join(urls, FILE_DELIMETER));

View File

@@ -127,6 +127,14 @@ springdoc:
paths-to-match: '/**' paths-to-match: '/**'
packages-to-scan: com.ruoyi.web.controller.tool packages-to-scan: com.ruoyi.web.controller.tool
# MinIO配置
minio:
enabled: true
endpoint: http://49.232.154.205:10900
access-key: 4EsLD9g9OM09DT0HaBKj
secret-key: 05SFC5fleqTnaLRYBrxHiphMFYbGX5nYicj0WCHA
bucket: rtsp
# 防止XSS攻击 # 防止XSS攻击
xss: xss:
# 过滤开关 # 过滤开关

View File

@@ -59,6 +59,13 @@
<artifactId>ruoyi-system</artifactId> <artifactId>ruoyi-system</artifactId>
</dependency> </dependency>
<!-- MinIO Java Client -->
<dependency>
<groupId>io.minio</groupId>
<artifactId>minio</artifactId>
<version>8.5.11</version>
</dependency>
</dependencies> </dependencies>
</project> </project>

View File

@@ -0,0 +1,39 @@
package com.ruoyi.framework.config;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
@Component
@ConfigurationProperties(prefix = "minio")
public class MinioProperties {
/** 是否启用MinIO上传 */
private boolean enabled = true;
/** MinIO服务端地址例如 http://127.0.0.1:9000 */
private String endpoint;
/** 访问key */
private String accessKey;
/** 密钥 */
private String secretKey;
/** 桶名称 */
private String bucket;
/** 是否使用https */
private boolean secure = false;
public boolean isEnabled() { return enabled; }
public void setEnabled(boolean enabled) { this.enabled = enabled; }
public String getEndpoint() { return endpoint; }
public void setEndpoint(String endpoint) { this.endpoint = endpoint; }
public String getAccessKey() { return accessKey; }
public void setAccessKey(String accessKey) { this.accessKey = accessKey; }
public String getSecretKey() { return secretKey; }
public void setSecretKey(String secretKey) { this.secretKey = secretKey; }
public String getBucket() { return bucket; }
public void setBucket(String bucket) { this.bucket = bucket; }
public boolean isSecure() { return secure; }
public void setSecure(boolean secure) { this.secure = secure; }
}

View File

@@ -0,0 +1,78 @@
package com.ruoyi.framework.service;
import com.ruoyi.framework.config.MinioProperties;
import com.ruoyi.common.utils.file.FileUploadUtils;
import io.minio.BucketExistsArgs;
import io.minio.MakeBucketArgs;
import io.minio.MinioClient;
import io.minio.PutObjectArgs;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
import java.io.InputStream;
@Service
public class MinioService {
private final MinioClient minioClient;
private final MinioProperties properties;
@Autowired
public MinioService(MinioProperties properties) {
this.properties = properties;
this.minioClient = MinioClient.builder()
.endpoint(properties.getEndpoint())
.credentials(properties.getAccessKey(), properties.getSecretKey())
.build();
}
public UploadResult upload(MultipartFile file) throws Exception {
ensureBucket();
String objectName = FileUploadUtils.extractFilename(file);
try (InputStream is = file.getInputStream()) {
minioClient.putObject(
PutObjectArgs.builder()
.bucket(properties.getBucket())
.object(objectName)
.stream(is, file.getSize(), -1)
.contentType(file.getContentType())
.build()
);
}
String url = buildObjectUrl(objectName);
return new UploadResult(objectName, url);
}
public String buildObjectUrl(String objectName) {
String endpoint = properties.getEndpoint();
if (endpoint.endsWith("/")) {
endpoint = endpoint.substring(0, endpoint.length() - 1);
}
return endpoint + "/" + properties.getBucket() + "/" + objectName;
}
private void ensureBucket() throws Exception {
boolean exists = minioClient.bucketExists(BucketExistsArgs.builder()
.bucket(properties.getBucket())
.build());
if (!exists) {
minioClient.makeBucket(MakeBucketArgs.builder()
.bucket(properties.getBucket())
.build());
}
}
public static class UploadResult {
private final String objectName;
private final String url;
public UploadResult(String objectName, String url) {
this.objectName = objectName;
this.url = url;
}
public String getObjectName() { return objectName; }
public String getUrl() { return url; }
}
}

View File

@@ -71,6 +71,16 @@
<artifactId>commons-lang</artifactId> <artifactId>commons-lang</artifactId>
<version>2.6</version> <version>2.6</version>
</dependency> </dependency>
<dependency>
<groupId>org.testng</groupId>
<artifactId>testng</artifactId>
<version>7.11.0</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
</dependency>
</dependencies> </dependencies>