You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用S3TransferManager结合LocalStack下载时触发S3Exception(404)

解决LocalStack S3下载404问题的方案

核心问题排查与修复步骤

1. 强制S3AsyncClient指向LocalStack并开启路径样式访问

AWS SDK默认会请求真实S3服务,必须手动指定LocalStack的端点;另外LocalStack默认只支持路径样式访问,而新版SDK默认用虚拟主机样式,这是导致404的高频原因。

修改你的S3客户端配置类,补上关键配置:

S3AsyncClient s3AsyncClient = S3AsyncClient.builder()
        .endpointOverride(URI.create("http://localhost:4566")) // LocalStack S3默认端口
        .region(Region.US_EAST_1) // 和LocalStack启动区域保持一致
        .credentialsProvider(StaticCredentialsProvider.create(AwsBasicCredentials.create("test", "test")))
        .serviceConfiguration(config -> config.pathStyleAccessEnabled(true)) // 必须开启路径样式
        .build();

2. 验证LocalStack初始化脚本的正确性

检查Docker Compose挂载的初始化脚本,确保用awslocal(LocalStack专属CLI封装)而非原生aws命令创建桶和上传文件:

# Docker Compose示例配置
services:
  localstack:
    image: localstack/localstack:latest
    ports:
      - "4566:4566"
    environment:
      - SERVICES=s3
      - DEFAULT_REGION=us-east-1
    volumes:
      - "./init-scripts:/docker-entrypoint-initaws.d"

初始化脚本init-scripts/s3-init.sh里的命令要写对:

awslocal s3 mb s3://test
awslocal s3 cp ./test.txt s3://test/test.txt

3. 给测试加初始化等待逻辑

测试代码可能在LocalStack还没完成桶和文件创建时就执行,导致404。可以在测试类里加个简单的等待逻辑:

@BeforeEach
void setup() {
    // 重试10次,等待LocalStack服务就绪
    int retry = 0;
    while (retry < 10) {
        try (HttpClient client = HttpClient.newHttpClient()) {
            var request = HttpRequest.newBuilder()
                    .uri(URI.create("http://localhost:4566/health"))
                    .GET()
                    .build();
            var response = client.send(request, HttpResponse.BodyHandlers.ofString());
            if (response.statusCode() == 200) break;
        } catch (Exception e) {}
        
        try { Thread.sleep(1000); } catch (InterruptedException e) { Thread.currentThread().interrupt(); }
        retry++;
    }
}

4. 确保区域配置完全一致

以下三处的区域必须完全相同:

  • LocalStack启动时的DEFAULT_REGION环境变量
  • S3AsyncClient配置的region参数
  • 初始化脚本创建桶时的区域(如果没指定,会用LocalStack默认区域,要和上面保持一致)

测试代码调整示例

确认下载逻辑里的桶名、对象键和初始化的一致:

TransferManager transferManager = TransferManagerBuilder.standard()
        .s3Client(s3AsyncClient)
        .build();

File downloadFile = new File("./downloaded-test.txt");
Download download = transferManager.download("test", "test.txt", downloadFile);
download.waitForCompletion();

// 断言文件存在且内容匹配
assertTrue(downloadFile.exists());
assertEquals("test content", Files.readString(downloadFile.toPath()));

内容的提问来源于stack exchange,提问作者Kunal Varpe

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.06 01:20:22