diff --git a/src/main/java/com/aida/seller/common/exception/GlobalExceptionHandler.java b/src/main/java/com/aida/seller/common/exception/GlobalExceptionHandler.java index 3920cee..9cad20b 100644 --- a/src/main/java/com/aida/seller/common/exception/GlobalExceptionHandler.java +++ b/src/main/java/com/aida/seller/common/exception/GlobalExceptionHandler.java @@ -62,12 +62,9 @@ public class GlobalExceptionHandler { @ExceptionHandler(MinioException.class) public ResponseEntity handleMinioException(MinioException e) { log.error("[MinioException] {}", e.getMessage(), e); - String message = e.getMessage(); - if (message != null && (message.contains("文件不能为空") || message.contains("不能为空"))) { - Response response = Response.error(HttpStatus.INTERNAL_SERVER_ERROR.value(), "File cannot be empty"); - return new ResponseEntity<>(response, HttpStatus.INTERNAL_SERVER_ERROR); - } - Response response = Response.error(HttpStatus.INTERNAL_SERVER_ERROR.value(), "File storage service error"); - return new ResponseEntity<>(response, HttpStatus.INTERNAL_SERVER_ERROR); + return new ResponseEntity<>( + Response.error(e.getMessage()), + HttpStatus.INTERNAL_SERVER_ERROR + ); } } diff --git a/src/main/java/com/aida/seller/common/exception/MinioException.java b/src/main/java/com/aida/seller/common/exception/MinioException.java index 1549f1b..efe58ee 100644 --- a/src/main/java/com/aida/seller/common/exception/MinioException.java +++ b/src/main/java/com/aida/seller/common/exception/MinioException.java @@ -1,9 +1,18 @@ package com.aida.seller.common.exception; +import com.aida.seller.common.context.UserContext; +import com.aida.seller.model.vo.AuthPrincipalVo; + +import java.io.InputStream; +import java.io.InputStreamReader; +import java.nio.charset.StandardCharsets; +import java.util.PropertyResourceBundle; +import java.util.ResourceBundle; + /** * MinIO 操作异常类 - * 用于处理 MinIO 相关的业务异常 - * + * 用于处理 MinIO 相关的业务异常,支持国际化 + * * @author Aida * @since 2024-01-01 */ @@ -11,68 +20,55 @@ public class MinioException extends RuntimeException { private static final long serialVersionUID = 1L; - /** - * 错误码 - */ private String errorCode; - /** - * 构造函数 - * - * @param message 异常信息 - */ public MinioException(String message) { - super(message); + super(getMessageFromResource(message, getUserLocale())); } - /** - * 构造函数 - * - * @param message 异常信息 - * @param cause 原因 - */ public MinioException(String message, Throwable cause) { - super(message, cause); + super(getMessageFromResource(message, getUserLocale()), cause); } - /** - * 构造函数 - * - * @param errorCode 错误码 - * @param message 异常信息 - */ public MinioException(String errorCode, String message) { - super(message); + super(getMessageFromResource(message, getUserLocale())); this.errorCode = errorCode; } - /** - * 构造函数 - * - * @param errorCode 错误码 - * @param message 异常信息 - * @param cause 原因 - */ public MinioException(String errorCode, String message, Throwable cause) { - super(message, cause); + super(getMessageFromResource(message, getUserLocale()), cause); this.errorCode = errorCode; } - /** - * 获取错误码 - * - * @return 错误码 - */ public String getErrorCode() { return errorCode; } - /** - * 设置错误码 - * - * @param errorCode 错误码 - */ public void setErrorCode(String errorCode) { this.errorCode = errorCode; } -} \ No newline at end of file + + private static String getUserLocale() { + AuthPrincipalVo userInfo = UserContext.getUserHolder(); + if (userInfo == null) return "en"; + String lang = userInfo.getLanguage(); + if (lang == null) return "en"; + if ("CHINESE_SIMPLIFIED".equalsIgnoreCase(lang)) return "zh"; + if ("ENGLISH".equalsIgnoreCase(lang)) return "en"; + return "en"; + } + + public static String getMessageFromResource(String msg, String locale) { + if (msg == null) return null; + try (InputStream is = MinioException.class.getClassLoader() + .getResourceAsStream("messages_" + locale + ".properties")) { + if (is != null) { + ResourceBundle bundle = new PropertyResourceBundle( + new InputStreamReader(is, StandardCharsets.UTF_8)); + if (bundle.containsKey(msg)) return bundle.getString(msg); + } + } catch (Exception ignored) { + } + return msg; + } +} diff --git a/src/main/java/com/aida/seller/util/MinioUtil.java b/src/main/java/com/aida/seller/util/MinioUtil.java index 5fc78bd..d2be3b4 100644 --- a/src/main/java/com/aida/seller/util/MinioUtil.java +++ b/src/main/java/com/aida/seller/util/MinioUtil.java @@ -71,8 +71,7 @@ public class MinioUtil { return bucketName + "/" + filePath; } catch (Exception e) { log.error("文件上传失败: {}", e.getMessage(), e); - // throw new MinioException("文件上传失败", e); - throw new MinioException("File upload failed", e); + throw new MinioException("minio.upload.failed", e); } } @@ -112,8 +111,7 @@ public class MinioUtil { return url; } catch (Exception e) { log.error("获取临时访问地址失败: {}", e.getMessage(), e); - // throw new MinioException("获取临时访问地址失败", e); - throw new MinioException("Failed to get temporary access URL", e); + throw new MinioException("minio.get.presigned.url.failed", e); } } @@ -125,8 +123,7 @@ public class MinioUtil { try { int index = objectPath.indexOf("/"); if (index == -1) { - // throw new MinioException("无效的对象路径,格式应为 bucketName/filePath"); - throw new MinioException("Invalid object path, format should be bucketName/filePath"); + throw new MinioException("minio.invalid.object.path"); } String bucketName = objectPath.substring(0, index); String filePath = objectPath.substring(index + 1); @@ -139,8 +136,7 @@ public class MinioUtil { log.info("文件删除成功,桶名: {}, 文件路径: {}", bucketName, filePath); } catch (Exception e) { log.error("文件删除失败: {}", e.getMessage(), e); - // throw new MinioException("文件删除失败", e); - throw new MinioException("File deletion failed", e); + throw new MinioException("minio.delete.failed", e); } } @@ -153,8 +149,7 @@ public class MinioUtil { String firstPath = objectPaths.get(0); int index = firstPath.indexOf("/"); if (index == -1) { - // throw new MinioException("无效的对象路径,格式应为 bucketName/filePath"); - throw new MinioException("Invalid object path, format should be bucketName/filePath"); + throw new MinioException("minio.invalid.object.path"); } String bucketName = firstPath.substring(0, index); @@ -180,8 +175,7 @@ public class MinioUtil { log.info("批量删除文件成功,桶名: {}, 文件数量: {}", bucketName, objectPaths.size()); } catch (Exception e) { log.error("批量删除文件失败: {}", e.getMessage(), e); - // throw new MinioException("批量删除文件失败", e); - throw new MinioException("Batch file deletion failed", e); + throw new MinioException("minio.batch.delete.failed", e); } } @@ -205,8 +199,7 @@ public class MinioUtil { return uploadImage(imageBytes, bucketName, filePath, contentType); } catch (Exception e) { log.error("base64图片上传失败: {}", e.getMessage(), e); - // throw new MinioException("base64图片上传失败", e); - throw new MinioException("Base64 image upload failed", e); + throw new MinioException("minio.base64.upload.failed", e); } } @@ -234,8 +227,7 @@ public class MinioUtil { return bucketName + "/" + filePath; } catch (Exception e) { log.error("文件上传失败: {}", e.getMessage(), e); - // throw new MinioException("文件上传失败", e); - throw new MinioException("File upload failed", e); + throw new MinioException("minio.upload.failed", e); } } @@ -246,8 +238,7 @@ public class MinioUtil { public String uploadBytes(byte[] bytes, String objectName, String contentType, String bucketName) { if (bytes == null || bytes.length == 0) { - // throw new MinioException("文件内容不能为空"); - throw new MinioException("File content cannot be empty"); + throw new MinioException("minio.file.content.empty"); } try { @@ -264,16 +255,14 @@ public class MinioUtil { return bucketName + "/" + objectName; } catch (Exception e) { log.error("字节数组上传失败: {}", e.getMessage(), e); - // throw new MinioException("字节数组上传失败", e); - throw new MinioException("Byte array upload failed", e); + throw new MinioException("minio.bytes.upload.failed", e); } } public InputStream downloadFile(String logicalPath) { int index = logicalPath.indexOf("/"); if (index <= 0) { - // throw new MinioException("逻辑路径格式错误,应包含桶名: " + logicalPath); - throw new MinioException("Invalid logical path format, should contain bucket name: " + logicalPath); + throw new MinioException("minio.logical.path.format.error"); } String bucketName = logicalPath.substring(0, index); @@ -282,13 +271,11 @@ public class MinioUtil { try { boolean bucketExists = minioClient.bucketExists(BucketExistsArgs.builder().bucket(bucketName).build()); if (!bucketExists) { - // throw new MinioException("桶不存在: " + bucketName); - throw new MinioException("Bucket does not exist: " + bucketName); + throw new MinioException("minio.bucket.not.exists"); } } catch (Exception e) { log.error("验证桶存在性失败: {}", e.getMessage(), e); - // throw new MinioException("验证桶存在性失败bucketName:{}", bucketName); - throw new MinioException("Failed to verify bucket existence, bucketName: " + bucketName, e); + throw new MinioException("minio.verify.bucket.failed"); } try { @@ -300,8 +287,7 @@ public class MinioUtil { ); } catch (Exception e) { log.error("文件下载失败: {}", e.getMessage(), e); - // throw new MinioException("文件下载失败", e); - throw new MinioException("File download failed", e); + throw new MinioException("minio.download.failed", e); } } @@ -316,8 +302,7 @@ public class MinioUtil { int firstSlashIndex = path.indexOf("/"); if (firstSlashIndex <= 0) { - // throw new MinioException("预签名URL路径格式无效,应包含桶名和对象名: " + presignedUrl); - throw new MinioException("Invalid presigned URL path format, should contain bucket name and object name: " + presignedUrl); + throw new MinioException("minio.presigned.url.format.invalid"); } String bucketName = path.substring(0, firstSlashIndex); @@ -326,8 +311,7 @@ public class MinioUtil { return bucketName + "/" + objectName; } catch (Exception e) { log.error("预签名URL解析失败: {}", e.getMessage(), e); - // throw new MinioException("预签名URL解析失败", e); - throw new MinioException("Failed to parse presigned URL", e); + throw new MinioException("minio.presigned.url.parse.failed", e); } } @@ -453,16 +437,14 @@ public class MinioUtil { public String convertToLogicalPath(String url) { if (url == null || url.isEmpty()) { - // throw new MinioException("URL不能为空"); - throw new MinioException("URL cannot be empty"); + throw new MinioException("minio.url.cannot.be.empty"); } if (isMinioLogicalPath(url)) { return url.trim(); } else if (isPresignedUrl(url)) { return getLogicalPathFromPresignedUrl(url); } else { - // throw new MinioException("无法识别的MinIO资源格式: " + url + ",请提供有效的预签名URL或逻辑路径"); - throw new MinioException("Unrecognized MinIO resource format: " + url + ", please provide a valid presigned URL or logical path"); + throw new MinioException("minio.resource.format.unrecognized"); } } diff --git a/src/main/resources/messages_en.properties b/src/main/resources/messages_en.properties index 953e62d..a25eaf1 100644 --- a/src/main/resources/messages_en.properties +++ b/src/main/resources/messages_en.properties @@ -321,3 +321,19 @@ GENERATE=Generate Sketch EXTRACT=Extract Sketch CHILD=Child ADULT=Adult +minio.upload.failed=File upload failed. +minio.get.presigned.url.failed=Failed to get temporary access URL. +minio.invalid.object.path=Invalid object path, format should be bucketName/filePath. +minio.delete.failed=File deletion failed. +minio.batch.delete.failed=Batch file deletion failed. +minio.base64.upload.failed=Base64 image upload failed. +minio.file.content.empty=File content cannot be empty. +minio.bytes.upload.failed=Byte array upload failed. +minio.logical.path.format.error=Logical path format error, should contain bucket name. +minio.bucket.not.exists=Bucket does not exist: {0}. +minio.verify.bucket.failed=Failed to verify bucket existence: {0}. +minio.download.failed=File download failed. +minio.presigned.url.format.invalid=Presigned URL path format invalid, should contain bucket name and object name. +minio.presigned.url.parse.failed=Failed to parse presigned URL. +minio.url.cannot.be.empty=URL cannot be empty. +minio.resource.format.unrecognized=Unrecognized MinIO resource format: {0}, please provide a valid presigned URL or logical path. diff --git a/src/main/resources/messages_zh.properties b/src/main/resources/messages_zh.properties index 791ecdc..1bf698e 100644 --- a/src/main/resources/messages_zh.properties +++ b/src/main/resources/messages_zh.properties @@ -318,3 +318,19 @@ GENERATE=生成线稿 EXTRACT=提取线稿 CHILD=儿童 ADULT=成人 +minio.upload.failed=文件上传失败。 +minio.get.presigned.url.failed=获取临时访问地址失败。 +minio.invalid.object.path=无效的对象路径,格式应为 bucketName/filePath。 +minio.delete.failed=文件删除失败。 +minio.batch.delete.failed=批量删除文件失败。 +minio.base64.upload.failed=base64图片上传失败。 +minio.file.content.empty=文件内容不能为空。 +minio.bytes.upload.failed=字节数组上传失败。 +minio.logical.path.format.error=逻辑路径格式错误,应包含桶名。 +minio.bucket.not.exists=桶不存在: {0}。 +minio.verify.bucket.failed=验证桶存在性失败: {0}。 +minio.download.failed=文件下载失败。 +minio.presigned.url.format.invalid=预签名URL路径格式无效,应包含桶名和对象名。 +minio.presigned.url.parse.failed=预签名URL解析失败。 +minio.url.cannot.be.empty=URL不能为空。 +minio.resource.format.unrecognized=无法识别的MinIO资源格式: {0},请提供有效的预签名URL或逻辑路径。