1. 简介
本文将介绍如何使用 Java 编程方式与 Amazon S3(简单存储服务)进行交互。S3 的结构非常简单:每个 bucket 可存储任意数量的对象,通过 SOAP 接口或 REST 风格 API 访问。
我们将使用 AWS SDK for Java 完成以下操作:
- 创建、列出和删除 S3 bucket
- 上传、列出、下载、复制、移动、重命名和删除 bucket 中的对象
2. Maven 依赖
首先添加 AWS SDK 依赖:
<dependency>
<groupId>software.amazon.awssdk</groupId>
<artifactId>s3</artifactId>
<version>2.20.52</version>
</dependency>
⚠️ 最新版本请查阅 Maven Central
3. 前置条件
使用 AWS SDK 需要准备以下内容:
AWS 账户
需要一个 Amazon Web Services 账户,没有可注册新账户AWS 安全凭证
两种获取方式:选择 AWS 区域
需选择存储 S3 数据的区域(不同区域价格不同,详见官方文档)。本文使用 US East (Ohio, region us-east-2)
4. 创建客户端连接
首先创建 S3 客户端连接:
AWSCredentials credentials = new BasicAWSCredentials(
"<AWS accesskey>",
"<AWS secretkey>"
);
然后配置客户端:
AmazonS3 s3client = AmazonS3ClientBuilder
.standard()
.withCredentials(new AWSStaticCredentialsProvider(credentials))
.withRegion(Regions.US_EAST_2)
.build();
5. S3 Bucket 操作
5.1 创建 Bucket
⚠️ 重要:Bucket 命名空间全局共享,名称必须全局唯一!创建前需检查可用性。
Bucket 命名规则(官方文档):
- ✅ 长度 3-63 字符
- ❌ 不能包含下划线
- ❌ 不能以短横线结尾
- ❌ 不能有相邻句点
- ❌ 不能有句点+短横线组合(如
my-.bucket.com
无效) - ❌ 不能包含大写字母
创建示例:
String bucketName = "baeldung-bucket";
if(s3client.doesBucketExist(bucketName)) {
LOG.info("Bucket 名称不可用,请更换其他名称");
return;
}
CreateBucketRequest bucketRequest = CreateBucketRequest.builder()
.bucket(bucketName)
.build();
s3Client.createBucket(bucketRequest);
5.2 列出 Bucket
使用 listBuckets()
获取所有 bucket:
ListBucketsResponse listBucketsResponse = s3Client.listBuckets();
List<Bucket> buckets = listBucketsResponse.buckets();
System.out.println("Buckets:");
for (Bucket bucket : buckets) {
System.out.println(bucket.name());
}
输出示例:
baeldung-bucket
baeldung-bucket-test2
elasticbeanstalk-us-east-2
5.3 删除 Bucket
⚠️ 必须先清空 bucket,否则会抛出异常!
只有 bucket 所有者才能删除(无论权限设置如何):
try {
DeleteBucketRequest deleteBucketRequest = DeleteBucketRequest.builder()
.bucket(bucketName)
.build();
s3Client.deleteBucket(deleteBucketRequest);
System.out.println("成功删除 bucket: " + bucketName);
} catch (S3Exception e) {
System.err.println(e.getMessage());
System.exit(1);
}
6. S3 对象操作
S3 中的文件或数据集合称为对象(Object)。支持的操作包括:
- 上传、列出、下载
- 复制、移动、重命名
- 删除(单个/批量)
6.1 上传对象
简单粗暴的上传方式:
PutObjectRequest request = PutObjectRequest.builder()
.bucket(bucketName)
.key(key)
.build();
return s3Client.putObject(request, Path.of(file.toURI()) );
6.2 列出对象
使用 listObjectsV2()
列出 bucket 中所有对象:
ListObjectsV2Request listObjectsV2Request = ListObjectsV2Request.builder()
.bucket(bucketName)
.build();
ListObjectsV2Response listObjectsV2Response = s3Client.listObjectsV2(listObjectsV2Request);
List<S3Object> contents = listObjectsV2Response.contents();
System.out.println("Bucket 中的对象数量: " + contents.stream().count());
contents.stream().forEach(System.out::println);
6.3 下载对象
下载对象到本地文件:
GetObjectRequest objectRequest = GetObjectRequest.builder()
.bucket(bucketName)
.key(objectKey)
.build();
ResponseBytes<GetObjectResponse> responseResponseBytes = s3Client.getObjectAsBytes(objectRequest);
byte[] data = responseResponseBytes.asByteArray();
// 写入本地文件
java.io.File myFile = new java.io.File("/Users/johndoe/Desktop/hello.txt" );
OutputStream os = new FileOutputStream(myFile);
os.write(data);
System.out.println("成功从 S3 对象获取字节数据");
os.close();
6.4 复制、重命名和移动对象
复制对象需要四个参数:
- 源 bucket 名称
- 源对象键
- 目标 bucket 名称(可与源相同)
- 目标对象键
CopyObjectRequest copyObjectRequest = CopyObjectRequest.builder()
.sourceBucket(sourceBucketName)
.sourceKey(sourceKey)
.destinationBucket(destinationBucketName)
.destinationKey(destinationKey)
.build();
return s3Client.copyObject(copyObjectRequest);
💡 移动/重命名技巧:先复制对象,再删除原对象
6.5 删除对象
删除单个对象:
DeleteObjectRequest deleteObjectRequest = DeleteObjectRequest.builder()
.bucket(bucketName)
.key(objectKey)
.build();
s3Client.deleteObject(deleteObjectRequest);
6.6 批量删除对象
一次性删除多个对象:
ArrayList<ObjectIdentifier> toDelete = new ArrayList<>();
for(String objKey : keys) {
toDelete.add(ObjectIdentifier.builder()
.key(objKey)
.build());
}
DeleteObjectsRequest deleteObjectRequest = DeleteObjectsRequest.builder()
.bucket(bucketName)
.delete(Delete.builder()
.objects(toDelete).build())
.build();
s3Client.deleteObjects(deleteObjectRequest);
7. 总结
本文介绍了 S3 的基础操作,包括 bucket 和对象级别的核心功能。完整代码示例可在 GitHub 查看。
踩坑提醒:
- 始终检查 bucket 名称唯一性
- 删除 bucket 前必须清空
- 复制操作是移动/重命名的基础