From 86bc7e2720782af132dc51cc93d0052f259b342f Mon Sep 17 00:00:00 2001 From: 司徒俊杰 Date: Mon, 24 Aug 2026 13:58:11 +0800 Subject: [PATCH] fix(infra): use provider endpoint for OSS presign --- yudao-module-infra/src/main/java/cn/iocoder/yudao/module/infra/framework/file/core/client/s3/S3FileClient.java | 6 ++++++ yudao-module-infra/src/test/java/cn/iocoder/yudao/module/infra/framework/file/core/s3/S3FileClientTest.java | 36 ++++++++++++++++++++++++++++++++++++ 2 files changed, 42 insertions(+), 0 deletions(-) diff --git a/yudao-module-infra/src/main/java/cn/iocoder/yudao/module/infra/framework/file/core/client/s3/S3FileClient.java b/yudao-module-infra/src/main/java/cn/iocoder/yudao/module/infra/framework/file/core/client/s3/S3FileClient.java index 98d37d8..4339904 100644 --- a/yudao-module-infra/src/main/java/cn/iocoder/yudao/module/infra/framework/file/core/client/s3/S3FileClient.java +++ b/yudao-module-infra/src/main/java/cn/iocoder/yudao/module/infra/framework/file/core/client/s3/S3FileClient.java @@ -173,6 +173,12 @@ public class S3FileClient extends AbstractFileClient { * @return 节点地址 */ private String buildPresignerEndpoint() { + // 阿里云 OSS、七牛云的自定义域名仅用于文件访问,不能作为 S3 签名节点。 + // Presigner 必须使用服务商提供的 endpoint,否则生成的签名无法用于直传。 + if (StrUtil.contains(config.getEndpoint(), S3FileClientConfig.ENDPOINT_ALIYUN) + || StrUtil.contains(config.getEndpoint(), S3FileClientConfig.ENDPOINT_QINIU)) { + return buildEndpoint(); + } // 补全 domain if (StrUtil.isEmpty(config.getDomain())) { config.setDomain(buildDomain()); diff --git a/yudao-module-infra/src/test/java/cn/iocoder/yudao/module/infra/framework/file/core/s3/S3FileClientTest.java b/yudao-module-infra/src/test/java/cn/iocoder/yudao/module/infra/framework/file/core/s3/S3FileClientTest.java index 8a3e2cd..73355ad 100644 --- a/yudao-module-infra/src/test/java/cn/iocoder/yudao/module/infra/framework/file/core/s3/S3FileClientTest.java +++ b/yudao-module-infra/src/test/java/cn/iocoder/yudao/module/infra/framework/file/core/s3/S3FileClientTest.java @@ -70,6 +70,42 @@ public class S3FileClientTest { } @Test + public void testPresignPutUrl_aliyunUsesEndpointInsteadOfCustomDomain() { + S3FileClientConfig config = new S3FileClientConfig(); + config.setAccessKey("access-key"); + config.setAccessSecret("access-secret"); + config.setBucket("test-bucket"); + config.setDomain("https://custom.example.com"); + config.setEndpoint("oss-cn-beijing.aliyuncs.com"); + config.setEnablePathStyleAccess(false); + config.setEnablePublicAccess(false); + S3FileClient client = new S3FileClient(0L, config); + client.init(); + + String result = client.presignPutUrl("avatar.jpg"); + + assertTrue(result.startsWith("https://test-bucket.oss-cn-beijing.aliyuncs.com/")); + } + + @Test + public void testPresignPutUrl_qiniuUsesEndpointInsteadOfCustomDomain() { + S3FileClientConfig config = new S3FileClientConfig(); + config.setAccessKey("access-key"); + config.setAccessSecret("access-secret"); + config.setBucket("test-bucket"); + config.setDomain("https://custom.example.com"); + config.setEndpoint("s3-cn-south-1.qiniucs.com"); + config.setEnablePathStyleAccess(false); + config.setEnablePublicAccess(false); + S3FileClient client = new S3FileClient(0L, config); + client.init(); + + String result = client.presignPutUrl("avatar.jpg"); + + assertTrue(result.startsWith("https://test-bucket.s3-cn-south-1.qiniucs.com/")); + } + + @Test @Disabled // MinIO,如果要集成测试,可以注释本行 public void testMinIO() throws Exception { S3FileClientConfig config = new S3FileClientConfig(); -- libgit2 0.21.4