关于 aws-sdk-java-v2-s3
面向 Java 开发者的 AWS SDK for Java 2.x S3 操作实践技能,涵盖存储桶与对象管理、传输及临时访问链接。也提供大文件分段传输和 Spring Boot 集成指导。
主要功能
- 01创建、列出和删除存储桶
- 02上传、下载及复制对象
- 03处理分段上传和 Transfer Manager
- 04生成预签名 URL
- 05配置元数据、加密和存储类别
适用场景
- 01管理 S3 存储桶和对象
- 02传输大型文件
- 03为对象提供临时访问链接
- 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.mds3-object-operations.mds3-spring-boot-integration.mds3-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 个键 |
| 预签名 URL | presigner.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);
}
参考资料
- references/s3-client-setup.md — 客户端配置和基本操作
- references/s3-object-operations.md — 高级对象操作
- references/s3-transfer-patterns.md — Transfer Manager 和分段上传
- references/s3-spring-boot-integration.md — Spring Boot 集成模式
- AWS S3 开发者指南
- AWS SDK for Java 2.x S3 API
相关技能
aws-sdk-java-v2-core- AWS SDK 核心模式和配置spring-boot-dependency-injection- Spring 依赖注入模式
评论
支持 Markdown