mcpField
A
aws-sdk-java-v2-s3

aws-sdk-java-v2-s3

github.com/giuseppe-trisciuoglio云与 DevOps3653.7k 次安装7 周前更新
代码仓库

关于 aws-sdk-java-v2-s3

面向 Java 开发者的 AWS SDK for Java 2.x S3 操作实践技能,涵盖存储桶与对象管理、传输及临时访问链接。也提供大文件分段传输和 Spring Boot 集成指导。

主要功能

  1. 01创建、列出和删除存储桶
  2. 02上传、下载及复制对象
  3. 03处理分段上传和 Transfer Manager
  4. 04生成预签名 URL
  5. 05配置元数据、加密和存储类别

适用场景

  1. 01管理 S3 存储桶和对象
  2. 02传输大型文件
  3. 03为对象提供临时访问链接
  4. 04在 Spring Boot 应用中接入 S3

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/giuseppe-trisciuoglio/developer-kit --skill aws-sdk-java-v2-s3

安装后在 Claude Code 中输入/aws-sdk-java-v2-s3确认已加载。

包含的文件

除 SKILL.md 外,安装时一起下载的参考资料和脚本。

references/
s3-client-setup.md
s3-object-operations.md
s3-spring-boot-integration.md
s3-transfer-patterns.md

详细介绍

AWS SDK for Java 2.x - Amazon S3

概述

介绍使用 AWS SDK for Java 2.x 执行 S3 操作的模式:存储桶管理、支持分段上传的对象上传和下载、预签名 URL、S3 Transfer Manager,以及 S3 专用配置。

适用场景

  • 使用适当的配置创建、列出或删除 S3 存储桶
  • 上传或下载 S3 对象,并设置元数据和加密
  • 对大文件(>100MB)使用分段上传,并处理错误
  • 生成预签名 URL,以便临时访问 S3 对象
  • 在 S3 存储桶之间复制或移动对象,并保留元数据
  • 设置对象元数据、存储类别和访问控制
  • 使用 S3 Transfer Manager 优化文件传输
  • 将 S3 集成到 Spring Boot 应用中,用于云存储

快速参考

操作方法说明
创建存储桶createBucket()使用 waiter().waitUntilBucketExists() 等待
上传对象putObject()使用 RequestBody.fromFile()
下载对象getObject()将数据流传输到文件或内存
删除对象deleteObjects()每批最多 1000 个键
预签名 URLpresigner.presignGetObject()最长有效期为 7 天
存储类别
类别用途
STANDARD频繁访问的数据
STANDARD_IA不常访问的数据
GLACIER长期归档
INTELLIGENT_TIERING自动优化成本

操作说明

1. 添加依赖项
<dependency>
    <groupId>software.amazon.awssdk</groupId>
    <artifactId>s3</artifactId>
    <version>2.20.0</version>
</dependency>

<dependency>
    <groupId>software.amazon.awssdk</groupId>
    <artifactId>s3-transfer-manager</artifactId>
    <version>2.20.0</version>
</dependency>
2. 创建 S3 客户端
S3Client s3Client = S3Client.builder()
    .region(Region.US_EAST_1)
    .build();

// With retry logic
S3Client s3Client = S3Client.builder()
    .region(Region.US_EAST_1)
    .overrideConfiguration(b -> b
        .retryPolicy(RetryPolicy.builder()
            .numRetries(3)
            .build()))
    .build();
3. 创建存储桶
CreateBucketRequest request = CreateBucketRequest.builder()
    .bucket(bucketName)
    .build();

s3Client.createBucket(request);

// Wait until ready
s3Client.waiter().waitUntilBucketExists(
    HeadBucketRequest.builder().bucket(bucketName).build()
);
4. 上传对象
PutObjectRequest request = PutObjectRequest.builder()
    .bucket(bucketName)
    .key(key)
    .contentType("application/pdf")
    .serverSideEncryption(ServerSideEncryption.AES256)
    .storageClass(StorageClass.STANDARD_IA)
    .build();

s3Client.putObject(request, RequestBody.fromFile(Paths.get(filePath)));

// Validate upload completion
HeadObjectResponse headResp = s3Client.headObject(HeadObjectRequest.builder()
    .bucket(bucketName)
    .key(key)
    .build());
5. 下载对象
GetObjectRequest request = GetObjectRequest.builder()
    .bucket(bucketName)
    .key(key)
    .build();

s3Client.getObject(request, Paths.get(destPath));
6. 生成预签名 URL
try (S3Presigner presigner = S3Presigner.create()) {
    GetObjectRequest getRequest = GetObjectRequest.builder()
        .bucket(bucketName)
        .key(key)
        .build();

    GetObjectPresignRequest presignRequest = GetObjectPresignRequest.builder()
        .signatureDuration(Duration.ofMinutes(10))
        .getObjectRequest(getRequest)
        .build();

    String url = presigner.presignGetObject(presignRequest).url().toString();
}
7. 使用 Transfer Manager(大文件)
try (S3TransferManager tm = S3TransferManager.create()) {
    UploadFileRequest request = UploadFileRequest.builder()
        .putObjectRequest(req -> req.bucket(bucketName).key(key))
        .source(Paths.get(filePath))
        .build();

    FileUpload upload = tm.uploadFile(request);
    CompletedFileUpload result = upload.completionFuture().join();
}

最佳实践

性能
  • 使用 S3 Transfer Manager:对 >100MB 的文件自动进行分段上传
  • 重复使用 S3 客户端:客户端是线程安全的,可在整个应用中重复使用
  • 启用异步操作:对 I/O 密集型操作使用 S3AsyncClient
  • 配置超时:为大文件操作设置适当的超时时间
安全
  • 使用临时凭证:使用 IAM 角色或 AWS STS 获取短期令牌
  • 启用加密:对敏感数据使用 AES-256 或 AWS KMS
  • 使用预签名 URL:通过临时访问避免暴露凭证
  • 验证元数据:清理用户提供的元数据
错误处理
  • 实现重试逻辑:对网络操作使用指数退避
  • 处理限流:妥善处理 429 响应
  • 清理失败操作:中止失败的分段上传
成本优化
  • 选择适当的存储类别:STANDARD、STANDARD_IA、INTELLIGENT_TIERING
  • 实施生命周期策略:自动转换/过期
  • 尽量减少 API 调用:尽可能使用批量操作

限制和警告

  • 对象大小:单次 PUT 的大小上限为 5GB;更大的文件请使用分段上传
  • 存储桶名称:必须在所有 AWS 账户中全局唯一
  • 对象不可变性:对象无法修改;必须整体替换
  • 最终一致性:上传后,列表操作可能会有轻微延迟
  • 预签名 URL:最长有效期为 7 天
  • 分段上传:除最后一段外,每段至少为 5MB

示例

带验证的完整上传工作流
// 1. Upload with validation
PutObjectRequest putRequest = PutObjectRequest.builder()
    .bucket(bucketName)
    .key(key)
    .contentType(contentType)
    .build();

s3Client.putObject(putRequest, RequestBody.fromFile(Paths.get(filePath)));

// 2. Validate with headObject
HeadObjectResponse headResp = s3Client.headObject(HeadObjectRequest.builder()
    .bucket(bucketName)
    .key(key)
    .build());

// 3. Verify metadata
long fileSize = Files.size(Paths.get(filePath));
if (headResp.contentLength() != fileSize) {
    throw new IllegalStateException("Upload size mismatch");
}
失败时中止的分段上传
// 1. Initiate multipart upload
CreateMultipartUploadRequest createRequest = CreateMultipartUploadRequest.builder()
    .bucket(bucketName)
    .key(key)
    .build();

CreateMultipartUploadResponse multipartUpload = s3Client.createMultipartUpload(createRequest);
String uploadId = multipartUpload.uploadId();

try {
    // 2. Upload parts
    List<CompletedPart> parts = new ArrayList<>();
    int partNumber = 1;
    byte[] fileBytes = Files.readAllBytes(Paths.get(filePath));
    int chunkSize = 5 * 1024 * 1024; // 5MB minimum

    for (int offset = 0; offset < fileBytes.length; offset += chunkSize) {
        int length = Math.min(chunkSize, fileBytes.length - offset);
        UploadPartRequest uploadPartRequest = UploadPartRequest.builder()
            .bucket(bucketName)
            .key(key)
            .uploadId(uploadId)
            .partNumber(partNumber)
            .build();

        UploadPartResponse partResponse = s3Client.uploadPart(uploadPartRequest,
            RequestBody.fromBytes(Arrays.copyOfRange(fileBytes, offset, offset + length)));

        parts.add(CompletedPart.builder()
            .partNumber(partNumber)
            .eTag(partResponse.eTag())
            .build());
        partNumber++;
    }

    // 3. Complete multipart upload
    CompleteMultipartUploadRequest completeRequest = CompleteMultipartUploadRequest.builder()
        .bucket(bucketName)
        .key(key)
        .uploadId(uploadId)
        .multipartUpload(CompletedMultipartUpload.builder().parts(parts).build())
        .build();
    s3Client.completeMultipartUpload(completeRequest);

} catch (Exception e) {
    // 4. Abort on failure
    AbortMultipartUploadRequest abortRequest = AbortMultipartUploadRequest.builder()
        .bucket(bucketName)
        .key(key)
        .uploadId(uploadId)
        .build();
    s3Client.abortMultipartUpload(abortRequest);
    throw new RuntimeException("Upload failed, cleanup performed", e);
}

参考资料

相关技能

  • aws-sdk-java-v2-core - AWS SDK 核心模式和配置
  • spring-boot-dependency-injection - Spring 依赖注入模式

评论

支持 Markdown