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 需要准备以下内容:

  1. AWS 账户
    需要一个 Amazon Web Services 账户,没有可注册新账户

  2. AWS 安全凭证
    两种获取方式:

  3. 选择 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 复制、重命名和移动对象

复制对象需要四个参数:

  1. 源 bucket 名称
  2. 源对象键
  3. 目标 bucket 名称(可与源相同)
  4. 目标对象键
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 前必须清空
  • 复制操作是移动/重命名的基础

原始标题:AWS S3 with Java