Просмотр исходного кода

!1465 fix: 【infra 基础设施】S3FileClient 配置的 region > 从 endpoint 解析的 region > 默认值 us-east-1
Merge pull request !1465 from puhui999/master-jdk17

芋道源码 месяцев назад: 6
Родитель
Сommit
94ee7d657d

+ 75 - 1
yudao-module-infra/src/main/java/cn/iocoder/yudao/module/infra/framework/file/core/client/s3/S3FileClient.java

@@ -47,7 +47,9 @@ public class S3FileClient extends AbstractFileClient<S3FileClientConfig> {
             config.setDomain(buildDomain());
         }
         // 初始化 S3 客户端
-        Region region = Region.of("us-east-1"); // 必须填,但填什么都行,常见的值有 "us-east-1",不填会报错
+        // 优先级:配置的 region > 从 endpoint 解析的 region > 默认值 us-east-1
+        String regionStr = resolveRegion();
+        Region region = Region.of(regionStr);
         AwsCredentialsProvider credentialsProvider = StaticCredentialsProvider.create(
                 AwsBasicCredentials.create(config.getAccessKey(), config.getAccessSecret()));
         URI endpoint = URI.create(buildEndpoint());
@@ -159,4 +161,76 @@ public class S3FileClient extends AbstractFileClient<S3FileClientConfig> {
         return StrUtil.format("https://{}", config.getEndpoint());
     }
 
+    /**
+     * 解析 AWS 区域
+     * 优先级:配置的 region > 从 endpoint 解析的 region > 默认值 us-east-1
+     *
+     * @return 区域字符串
+     */
+    private String resolveRegion() {
+        // 1. 如果配置了 region,直接使用
+        if (StrUtil.isNotEmpty(config.getRegion())) {
+            return config.getRegion();
+        }
+
+        // 2. 尝试从 endpoint 中解析 region
+        String endpoint = config.getEndpoint();
+        if (StrUtil.isEmpty(endpoint)) {
+            return "us-east-1";
+        }
+
+        // 移除协议头(http:// 或 https://)
+        String host = endpoint;
+        if (HttpUtil.isHttp(endpoint) || HttpUtil.isHttps(endpoint)) {
+            try {
+                host = URI.create(endpoint).getHost();
+            } catch (Exception e) {
+                // 解析失败,使用默认值
+                return "us-east-1";
+            }
+        }
+
+        if (StrUtil.isEmpty(host)) {
+            return "us-east-1";
+        }
+
+        // 3. AWS S3 格式:s3.us-west-2.amazonaws.com 或 s3.amazonaws.com
+        if (host.contains("amazonaws.com")) {
+            // 匹配 s3.{region}.amazonaws.com 格式
+            if (host.startsWith("s3.") && host.contains(".amazonaws.com")) {
+                String regionPart = host.substring(3, host.indexOf(".amazonaws.com"));
+                if (StrUtil.isNotEmpty(regionPart) && !regionPart.equals("accelerate")) {
+                    return regionPart;
+                }
+            }
+            // s3.amazonaws.com 或 s3-accelerate.amazonaws.com 使用默认值
+            return "us-east-1";
+        }
+
+        // 4. 阿里云 OSS 格式:oss-cn-beijing.aliyuncs.com
+        if (host.contains(S3FileClientConfig.ENDPOINT_ALIYUN)) {
+            // 匹配 oss-{region}.aliyuncs.com 格式
+            if (host.startsWith("oss-") && host.contains("." + S3FileClientConfig.ENDPOINT_ALIYUN)) {
+                String regionPart = host.substring(4, host.indexOf("." + S3FileClientConfig.ENDPOINT_ALIYUN));
+                if (StrUtil.isNotEmpty(regionPart)) {
+                    return regionPart;
+                }
+            }
+        }
+
+        // 5. 腾讯云 COS 格式:cos.ap-shanghai.myqcloud.com
+        if (host.contains(S3FileClientConfig.ENDPOINT_TENCENT)) {
+            // 匹配 cos.{region}.myqcloud.com 格式
+            if (host.startsWith("cos.") && host.contains("." + S3FileClientConfig.ENDPOINT_TENCENT)) {
+                String regionPart = host.substring(4, host.indexOf("." + S3FileClientConfig.ENDPOINT_TENCENT));
+                if (StrUtil.isNotEmpty(regionPart)) {
+                    return regionPart;
+                }
+            }
+        }
+
+        // 6. 其他情况(MinIO、七牛云等)使用默认值
+        return "us-east-1";
+    }
+
 }

+ 12 - 0
yudao-module-infra/src/main/java/cn/iocoder/yudao/module/infra/framework/file/core/client/s3/S3FileClientConfig.java

@@ -82,6 +82,18 @@ public class S3FileClientConfig implements FileClientConfig {
     @NotNull(message = "是否公开访问不能为空")
     private Boolean enablePublicAccess;
 
+    /**
+     * AWS 区域
+     * 1. AWS S3:https://docs.aws.amazon.com/general/latest/gr/s3.html 例如说,us-east-1、us-west-2
+     * 2. MinIO:可以填任意值,通常使用 us-east-1
+     * 3. 阿里云:不需要填写,会自动识别
+     * 4. 腾讯云:不需要填写,会自动识别
+     * 5. 七牛云:不需要填写,会自动识别
+     * 6. 华为云:不需要填写,会自动识别
+     * 7. 火山云:不需要填写,会自动识别
+     */
+    private String region;
+
     @SuppressWarnings("RedundantIfStatement")
     @AssertTrue(message = "domain 不能为空")
     @JsonIgnore