fix(file): 修复MinIO服务初始化和端口配置问题
- 修正MinIO端点端口号从10990改为10900 - 移除对MinioConfig的直接依赖注入,改用minioService.isInitialized()判断 - 重构MinioService实现延迟初始化和异常处理机制 - 添加初始化状态检查方法避免未初始化时的操作 - 更新依赖配置确保OkHttp和okio版本兼容性
This commit is contained in:
@@ -73,6 +73,19 @@
|
|||||||
<artifactId>ruoyi-cost</artifactId>
|
<artifactId>ruoyi-cost</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
|
<!-- MinIO 所需的 OkHttp 4.x(覆盖其他依赖传递的 3.x) -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.squareup.okhttp3</groupId>
|
||||||
|
<artifactId>okhttp</artifactId>
|
||||||
|
<version>4.12.0</version>
|
||||||
|
</dependency>
|
||||||
|
<!-- OkHttp 4.x 所需的 okio 3.x -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.squareup.okio</groupId>
|
||||||
|
<artifactId>okio</artifactId>
|
||||||
|
<version>3.6.0</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|
||||||
<build>
|
<build>
|
||||||
|
|||||||
@@ -13,7 +13,6 @@ import org.springframework.web.bind.annotation.PostMapping;
|
|||||||
import org.springframework.web.bind.annotation.RequestMapping;
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
import org.springframework.web.bind.annotation.RestController;
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
import org.springframework.web.multipart.MultipartFile;
|
import org.springframework.web.multipart.MultipartFile;
|
||||||
import com.ruoyi.common.config.MinioConfig;
|
|
||||||
import com.ruoyi.common.config.RuoYiConfig;
|
import com.ruoyi.common.config.RuoYiConfig;
|
||||||
import com.ruoyi.common.constant.Constants;
|
import com.ruoyi.common.constant.Constants;
|
||||||
import com.ruoyi.common.core.domain.AjaxResult;
|
import com.ruoyi.common.core.domain.AjaxResult;
|
||||||
@@ -41,9 +40,6 @@ public class CommonController
|
|||||||
@Autowired(required = false)
|
@Autowired(required = false)
|
||||||
private MinioService minioService;
|
private MinioService minioService;
|
||||||
|
|
||||||
@Autowired(required = false)
|
|
||||||
private MinioConfig minioConfig;
|
|
||||||
|
|
||||||
private static final String FILE_DELIMETER = ",";
|
private static final String FILE_DELIMETER = ",";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -220,6 +216,6 @@ public class CommonController
|
|||||||
*/
|
*/
|
||||||
private boolean isMinioEnabled()
|
private boolean isMinioEnabled()
|
||||||
{
|
{
|
||||||
return minioService != null && minioConfig != null && minioConfig.isEnabled();
|
return minioService != null && minioService.isInitialized();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
package com.ruoyi.web.controller.common;
|
package com.ruoyi.web.controller.common;
|
||||||
|
|
||||||
import com.ruoyi.common.annotation.Anonymous;
|
import com.ruoyi.common.annotation.Anonymous;
|
||||||
import com.ruoyi.common.config.MinioConfig;
|
|
||||||
import com.ruoyi.common.config.RuoYiConfig;
|
import com.ruoyi.common.config.RuoYiConfig;
|
||||||
import com.ruoyi.common.core.domain.AjaxResult;
|
import com.ruoyi.common.core.domain.AjaxResult;
|
||||||
import com.ruoyi.common.exception.NonCaptureException;
|
import com.ruoyi.common.exception.NonCaptureException;
|
||||||
@@ -31,9 +30,6 @@ public class FileUploadController {
|
|||||||
@Autowired(required = false)
|
@Autowired(required = false)
|
||||||
private MinioService minioService;
|
private MinioService minioService;
|
||||||
|
|
||||||
@Autowired(required = false)
|
|
||||||
private MinioConfig minioConfig;
|
|
||||||
|
|
||||||
@Anonymous
|
@Anonymous
|
||||||
@PostMapping("/upload")
|
@PostMapping("/upload")
|
||||||
@SuppressWarnings("DuplicatedCode")
|
@SuppressWarnings("DuplicatedCode")
|
||||||
@@ -75,6 +71,6 @@ public class FileUploadController {
|
|||||||
*/
|
*/
|
||||||
private boolean isMinioEnabled()
|
private boolean isMinioEnabled()
|
||||||
{
|
{
|
||||||
return minioService != null && minioConfig != null && minioConfig.isEnabled();
|
return minioService != null && minioService.isInitialized();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,7 +11,6 @@ import org.springframework.web.bind.annotation.RequestParam;
|
|||||||
import org.springframework.web.bind.annotation.RestController;
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
import org.springframework.web.multipart.MultipartFile;
|
import org.springframework.web.multipart.MultipartFile;
|
||||||
import com.ruoyi.common.annotation.Log;
|
import com.ruoyi.common.annotation.Log;
|
||||||
import com.ruoyi.common.config.MinioConfig;
|
|
||||||
import com.ruoyi.common.config.RuoYiConfig;
|
import com.ruoyi.common.config.RuoYiConfig;
|
||||||
import com.ruoyi.common.core.controller.BaseController;
|
import com.ruoyi.common.core.controller.BaseController;
|
||||||
import com.ruoyi.common.core.domain.AjaxResult;
|
import com.ruoyi.common.core.domain.AjaxResult;
|
||||||
@@ -44,9 +43,6 @@ public class SysProfileController extends BaseController
|
|||||||
@Autowired(required = false)
|
@Autowired(required = false)
|
||||||
private MinioService minioService;
|
private MinioService minioService;
|
||||||
|
|
||||||
@Autowired(required = false)
|
|
||||||
private MinioConfig minioConfig;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 个人信息
|
* 个人信息
|
||||||
*/
|
*/
|
||||||
@@ -159,6 +155,6 @@ public class SysProfileController extends BaseController
|
|||||||
*/
|
*/
|
||||||
private boolean isMinioEnabled()
|
private boolean isMinioEnabled()
|
||||||
{
|
{
|
||||||
return minioService != null && minioConfig != null && minioConfig.isEnabled();
|
return minioService != null && minioService.isInitialized();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ minio:
|
|||||||
# 是否启用(false 则使用本地文件系统)
|
# 是否启用(false 则使用本地文件系统)
|
||||||
enabled: true
|
enabled: true
|
||||||
# MinIO 服务地址
|
# MinIO 服务地址
|
||||||
endpoint: http://140.143.206.120:10990
|
endpoint: http://140.143.206.120:10900
|
||||||
# 访问密钥
|
# 访问密钥
|
||||||
accessKey: m4X4SsEOhEfTTiv7wI8X
|
accessKey: m4X4SsEOhEfTTiv7wI8X
|
||||||
# 秘密密钥
|
# 秘密密钥
|
||||||
|
|||||||
@@ -125,6 +125,12 @@
|
|||||||
<artifactId>okhttp</artifactId>
|
<artifactId>okhttp</artifactId>
|
||||||
<version>4.12.0</version>
|
<version>4.12.0</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<!-- OkHttp 4.x 所需的 okio 3.x -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.squareup.okio</groupId>
|
||||||
|
<artifactId>okio</artifactId>
|
||||||
|
<version>3.6.0</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
<!-- servlet包 -->
|
<!-- servlet包 -->
|
||||||
<dependency>
|
<dependency>
|
||||||
|
|||||||
@@ -12,16 +12,10 @@ import io.minio.PutObjectArgs;
|
|||||||
import io.minio.RemoveObjectArgs;
|
import io.minio.RemoveObjectArgs;
|
||||||
import io.minio.StatObjectArgs;
|
import io.minio.StatObjectArgs;
|
||||||
import io.minio.errors.ErrorResponseException;
|
import io.minio.errors.ErrorResponseException;
|
||||||
import io.minio.errors.InsufficientDataException;
|
|
||||||
import io.minio.errors.InternalException;
|
|
||||||
import io.minio.errors.InvalidResponseException;
|
|
||||||
import io.minio.errors.ServerException;
|
|
||||||
import io.minio.errors.XmlParserException;
|
|
||||||
|
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
import org.springframework.web.multipart.MultipartFile;
|
import org.springframework.web.multipart.MultipartFile;
|
||||||
|
|
||||||
@@ -35,45 +29,63 @@ import io.minio.http.Method;
|
|||||||
* @author ruoyi
|
* @author ruoyi
|
||||||
*/
|
*/
|
||||||
@Service
|
@Service
|
||||||
@ConditionalOnProperty(prefix = "minio", name = "enabled", havingValue = "true")
|
|
||||||
public class MinioService
|
public class MinioService
|
||||||
{
|
{
|
||||||
private static final Logger log = LoggerFactory.getLogger(MinioService.class);
|
private static final Logger log = LoggerFactory.getLogger(MinioService.class);
|
||||||
|
|
||||||
private MinioClient minioClient;
|
private MinioClient minioClient;
|
||||||
|
|
||||||
private MinioConfig minioConfig;
|
private MinioConfig minioConfig;
|
||||||
|
private volatile boolean initialized = false;
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
public MinioService(MinioConfig minioConfig)
|
public MinioService(MinioConfig minioConfig)
|
||||||
{
|
{
|
||||||
this.minioConfig = minioConfig;
|
this.minioConfig = minioConfig;
|
||||||
this.minioClient = MinioClient.builder()
|
if (!minioConfig.isEnabled())
|
||||||
.endpoint(minioConfig.getEndpoint())
|
{
|
||||||
.credentials(minioConfig.getAccessKey(), minioConfig.getSecretKey())
|
log.info("MinIO 未启用(minio.enabled=false),跳过初始化");
|
||||||
.build();
|
return;
|
||||||
ensureBucketExists();
|
}
|
||||||
|
try
|
||||||
|
{
|
||||||
|
this.minioClient = MinioClient.builder()
|
||||||
|
.endpoint(minioConfig.getEndpoint())
|
||||||
|
.credentials(minioConfig.getAccessKey(), minioConfig.getSecretKey())
|
||||||
|
.build();
|
||||||
|
ensureBucketExists();
|
||||||
|
this.initialized = true;
|
||||||
|
log.info("MinIO 客户端初始化成功: endpoint={}, bucket={}",
|
||||||
|
minioConfig.getEndpoint(), minioConfig.getBucketName());
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
log.warn("MinIO 初始化失败(应用将继续运行,上传降级为本地文件系统): {}", e.getMessage());
|
||||||
|
this.minioClient = null;
|
||||||
|
this.initialized = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 检查 MinIO 客户端是否已正确初始化
|
||||||
|
*/
|
||||||
|
private void checkInitialized()
|
||||||
|
{
|
||||||
|
if (!initialized || minioClient == null)
|
||||||
|
{
|
||||||
|
throw new IllegalStateException("MinIO 未启用或初始化失败,请检查配置");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 确保存储桶存在,不存在则自动创建
|
* 确保存储桶存在,不存在则自动创建
|
||||||
*/
|
*/
|
||||||
private void ensureBucketExists()
|
private void ensureBucketExists() throws Exception
|
||||||
{
|
{
|
||||||
try
|
String bucketName = minioConfig.getBucketName();
|
||||||
|
if (!minioClient.bucketExists(BucketExistsArgs.builder().bucket(bucketName).build()))
|
||||||
{
|
{
|
||||||
String bucketName = minioConfig.getBucketName();
|
minioClient.makeBucket(MakeBucketArgs.builder().bucket(bucketName).build());
|
||||||
boolean exists = minioClient.bucketExists(BucketExistsArgs.builder().bucket(bucketName).build());
|
log.info("MinIO 存储桶 [{}] 已自动创建", bucketName);
|
||||||
if (!exists)
|
|
||||||
{
|
|
||||||
minioClient.makeBucket(MakeBucketArgs.builder().bucket(bucketName).build());
|
|
||||||
log.info("MinIO 存储桶 [{}] 已自动创建", bucketName);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (Exception e)
|
|
||||||
{
|
|
||||||
log.error("MinIO 存储桶初始化失败", e);
|
|
||||||
throw new RuntimeException("MinIO 存储桶初始化失败: " + e.getMessage(), e);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -86,6 +98,7 @@ public class MinioService
|
|||||||
*/
|
*/
|
||||||
public String upload(MultipartFile file, String objectName) throws IOException
|
public String upload(MultipartFile file, String objectName) throws IOException
|
||||||
{
|
{
|
||||||
|
checkInitialized();
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
String contentType = file.getContentType() != null ? file.getContentType() : "application/octet-stream";
|
String contentType = file.getContentType() != null ? file.getContentType() : "application/octet-stream";
|
||||||
@@ -117,6 +130,7 @@ public class MinioService
|
|||||||
*/
|
*/
|
||||||
public String upload(InputStream stream, String objectName, long size, String contentType) throws IOException
|
public String upload(InputStream stream, String objectName, long size, String contentType) throws IOException
|
||||||
{
|
{
|
||||||
|
checkInitialized();
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
String ct = (contentType != null) ? contentType : "application/octet-stream";
|
String ct = (contentType != null) ? contentType : "application/octet-stream";
|
||||||
@@ -144,6 +158,7 @@ public class MinioService
|
|||||||
*/
|
*/
|
||||||
public String getUrl(String objectName)
|
public String getUrl(String objectName)
|
||||||
{
|
{
|
||||||
|
checkInitialized();
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
return minioClient.getPresignedObjectUrl(
|
return minioClient.getPresignedObjectUrl(
|
||||||
@@ -151,13 +166,12 @@ public class MinioService
|
|||||||
.method(Method.GET)
|
.method(Method.GET)
|
||||||
.bucket(minioConfig.getBucketName())
|
.bucket(minioConfig.getBucketName())
|
||||||
.object(objectName)
|
.object(objectName)
|
||||||
.expiry(7 * 24 * 60 * 60) // 7天有效期
|
.expiry(7 * 24 * 60 * 60)
|
||||||
.build());
|
.build());
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
log.warn("MinIO 获取 URL 失败: {}", objectName, e);
|
log.warn("MinIO 获取 URL 失败: {}", objectName, e);
|
||||||
// 返回拼接直连地址
|
|
||||||
return minioConfig.getEndpoint() + "/" + minioConfig.getBucketName() + "/" + objectName;
|
return minioConfig.getEndpoint() + "/" + minioConfig.getBucketName() + "/" + objectName;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -170,6 +184,7 @@ public class MinioService
|
|||||||
*/
|
*/
|
||||||
public void download(String objectName, OutputStream os) throws IOException
|
public void download(String objectName, OutputStream os) throws IOException
|
||||||
{
|
{
|
||||||
|
checkInitialized();
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
try (InputStream is = minioClient.getObject(
|
try (InputStream is = minioClient.getObject(
|
||||||
@@ -200,6 +215,7 @@ public class MinioService
|
|||||||
*/
|
*/
|
||||||
public void delete(String objectName) throws IOException
|
public void delete(String objectName) throws IOException
|
||||||
{
|
{
|
||||||
|
checkInitialized();
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
minioClient.removeObject(
|
minioClient.removeObject(
|
||||||
@@ -224,6 +240,10 @@ public class MinioService
|
|||||||
*/
|
*/
|
||||||
public boolean exists(String objectName)
|
public boolean exists(String objectName)
|
||||||
{
|
{
|
||||||
|
if (!initialized || minioClient == null)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
minioClient.statObject(
|
minioClient.statObject(
|
||||||
@@ -244,6 +264,14 @@ public class MinioService
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 判断 MinIO 是否已正确初始化并可用
|
||||||
|
*/
|
||||||
|
public boolean isInitialized()
|
||||||
|
{
|
||||||
|
return initialized && minioClient != null;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取 MinIO 配置
|
* 获取 MinIO 配置
|
||||||
*/
|
*/
|
||||||
|
|||||||
Reference in New Issue
Block a user