Commit f6090690fd5bd8b5286a398d12b8bc27012d148b

Authored by puhui999
1 parent 9fe1ce8e

fix: 【infra 基础设施】S3FileClient 配置的 region > 从 endpoint 解析的 region > 默认值 us-east-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> {
47 47 config.setDomain(buildDomain());
48 48 }
49 49 // 初始化 S3 客户端
50   - Region region = Region.of("us-east-1"); // 必须填,但填什么都行,常见的值有 "us-east-1",不填会报错
  50 + // 优先级:配置的 region > 从 endpoint 解析的 region > 默认值 us-east-1
  51 + String regionStr = resolveRegion();
  52 + Region region = Region.of(regionStr);
51 53 AwsCredentialsProvider credentialsProvider = StaticCredentialsProvider.create(
52 54 AwsBasicCredentials.create(config.getAccessKey(), config.getAccessSecret()));
53 55 URI endpoint = URI.create(buildEndpoint());
... ... @@ -159,4 +161,76 @@ public class S3FileClient extends AbstractFileClient<S3FileClientConfig> {
159 161 return StrUtil.format("https://{}", config.getEndpoint());
160 162 }
161 163  
  164 + /**
  165 + * 解析 AWS 区域
  166 + * 优先级:配置的 region > 从 endpoint 解析的 region > 默认值 us-east-1
  167 + *
  168 + * @return 区域字符串
  169 + */
  170 + private String resolveRegion() {
  171 + // 1. 如果配置了 region,直接使用
  172 + if (StrUtil.isNotEmpty(config.getRegion())) {
  173 + return config.getRegion();
  174 + }
  175 +
  176 + // 2. 尝试从 endpoint 中解析 region
  177 + String endpoint = config.getEndpoint();
  178 + if (StrUtil.isEmpty(endpoint)) {
  179 + return "us-east-1";
  180 + }
  181 +
  182 + // 移除协议头(http:// 或 https://)
  183 + String host = endpoint;
  184 + if (HttpUtil.isHttp(endpoint) || HttpUtil.isHttps(endpoint)) {
  185 + try {
  186 + host = URI.create(endpoint).getHost();
  187 + } catch (Exception e) {
  188 + // 解析失败,使用默认值
  189 + return "us-east-1";
  190 + }
  191 + }
  192 +
  193 + if (StrUtil.isEmpty(host)) {
  194 + return "us-east-1";
  195 + }
  196 +
  197 + // 3. AWS S3 格式:s3.us-west-2.amazonaws.com 或 s3.amazonaws.com
  198 + if (host.contains("amazonaws.com")) {
  199 + // 匹配 s3.{region}.amazonaws.com 格式
  200 + if (host.startsWith("s3.") && host.contains(".amazonaws.com")) {
  201 + String regionPart = host.substring(3, host.indexOf(".amazonaws.com"));
  202 + if (StrUtil.isNotEmpty(regionPart) && !regionPart.equals("accelerate")) {
  203 + return regionPart;
  204 + }
  205 + }
  206 + // s3.amazonaws.com 或 s3-accelerate.amazonaws.com 使用默认值
  207 + return "us-east-1";
  208 + }
  209 +
  210 + // 4. 阿里云 OSS 格式:oss-cn-beijing.aliyuncs.com
  211 + if (host.contains(S3FileClientConfig.ENDPOINT_ALIYUN)) {
  212 + // 匹配 oss-{region}.aliyuncs.com 格式
  213 + if (host.startsWith("oss-") && host.contains("." + S3FileClientConfig.ENDPOINT_ALIYUN)) {
  214 + String regionPart = host.substring(4, host.indexOf("." + S3FileClientConfig.ENDPOINT_ALIYUN));
  215 + if (StrUtil.isNotEmpty(regionPart)) {
  216 + return regionPart;
  217 + }
  218 + }
  219 + }
  220 +
  221 + // 5. 腾讯云 COS 格式:cos.ap-shanghai.myqcloud.com
  222 + if (host.contains(S3FileClientConfig.ENDPOINT_TENCENT)) {
  223 + // 匹配 cos.{region}.myqcloud.com 格式
  224 + if (host.startsWith("cos.") && host.contains("." + S3FileClientConfig.ENDPOINT_TENCENT)) {
  225 + String regionPart = host.substring(4, host.indexOf("." + S3FileClientConfig.ENDPOINT_TENCENT));
  226 + if (StrUtil.isNotEmpty(regionPart)) {
  227 + return regionPart;
  228 + }
  229 + }
  230 + }
  231 +
  232 + // 6. 其他情况(MinIO、七牛云等)使用默认值
  233 + return "us-east-1";
  234 + }
  235 +
162 236 }
... ...
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 {
82 82 @NotNull(message = "是否公开访问不能为空")
83 83 private Boolean enablePublicAccess;
84 84  
  85 + /**
  86 + * AWS 区域
  87 + * 1. AWS S3:https://docs.aws.amazon.com/general/latest/gr/s3.html 例如说,us-east-1、us-west-2
  88 + * 2. MinIO:可以填任意值,通常使用 us-east-1
  89 + * 3. 阿里云:不需要填写,会自动识别
  90 + * 4. 腾讯云:不需要填写,会自动识别
  91 + * 5. 七牛云:不需要填写,会自动识别
  92 + * 6. 华为云:不需要填写,会自动识别
  93 + * 7. 火山云:不需要填写,会自动识别
  94 + */
  95 + private String region;
  96 +
85 97 @SuppressWarnings("RedundantIfStatement")
86 98 @AssertTrue(message = "domain 不能为空")
87 99 @JsonIgnore
... ...