一、DeepSeek版
要使用Java列出Amazon S3中的所有目录和子目录路径,可以使用AWS SDK for Java (v2)。以下是完整的实现方法:
方法1:使用S3Client和listObjectsV2
import software.amazon.awssdk.regions.Region;
import software.amazon.awssdk.services.s3.S3Client;
import software.amazon.awssdk.services.s3.model.ListObjectsV2Request;
import software.amazon.awssdk.services.s3.model.ListObjectsV2Response;
import software.amazon.awssdk.services.s3.model.S3Object;
import java.util.HashSet;
import java.util.Set;
public class S3DirectoryLister {
public static void main(String[] args) {
String bucketName = "your-bucket-name";
String prefix = ""; // 可以从特定前缀开始
Set<String> directories = listS3Directories(bucketName, prefix);
System.out.println("Found directories:");
directories.forEach(System.out::println);
}
public static Set<String> listS3Directories(String bucketName, String prefix) {
S3Client s3 = S3Client.builder()
.region(Region.US_EAST_1) // 更改为你的区域
.build();
Set<String> directories = new HashSet<>();
ListObjectsV2Request request = ListObjectsV2Request.builder()
.bucket(bucketName)
.prefix(prefix)
.delimiter("/")
.build();
ListObjectsV2Response response;
do {
response = s3.listObjectsV2(request);
// 添加CommonPrefixes(目录)
if (response.commonPrefixes() != null) {
response.commonPrefixes().forEach(commonPrefix -> {
String dirPath = commonPrefix.prefix();
directories.add(dirPath);
// 递归列出子目录
directories.addAll(listS3Directories(bucketName, dirPath));
});
}
// 处理下一页(如果有)
request = request.toBuilder()
.continuationToken(response.nextContinuationToken())
.build();
} while (response.isTruncated());
s3.close();
return directories;
}
}
方法2:使用TransferManager(更高效)
import software.amazon.awssdk.core.async.AsyncResponseTransformer;
import software.amazon.awssdk.services.s3.S3AsyncClient;
import software.amazon.awssdk.services.s3.model.ListObjectsV2Request;
import software.amazon.awssdk.services.s3.model.ListObjectsV2Response;
import software.amazon.awssdk.services.s3.model.CommonPrefix;
import java.util.HashSet;
import java.util.Set;
import java.util.concurrent.CompletableFuture;
public class S3AsyncDirectoryLister {
public static void main(String[] args) {
String bucketName = "your-bucket-name";
String prefix = "";
Set<String> directories = new HashSet<>();
listS3DirectoriesAsync(S3AsyncClient.create(), bucketName, prefix, directories)
.thenRun(() -> {
System.out.println("Found directories:");
directories.forEach(System.out::println);
System.exit(0);
})
.exceptionally(e -> {
e.printStackTrace();
return null;
});
// 保持程序运行直到完成
try {
Thread.sleep(60000);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
public static CompletableFuture<Void> listS3DirectoriesAsync(
S3AsyncClient s3AsyncClient,
String bucketName,
String prefix,
Set<String> directories) {
ListObjectsV2Request request = ListObjectsV2Request.builder()
.bucket(bucketName)
.prefix(prefix)
.delimiter("/")
.build();
return s3AsyncClient.listObjectsV2(request)
.thenCompose(response -> {
// 处理当前响应
if (response.commonPrefixes() != null) {
for (CommonPrefix commonPrefix : response.commonPrefixes()) {
String dirPath = commonPrefix.prefix();
directories.add(dirPath);
}
// 为每个子目录启动新的异步请求
CompletableFuture<?>[] futures = response.commonPrefixes().stream()
.map(commonPrefix ->
listS3DirectoriesAsync(s3AsyncClient, bucketName,
commonPrefix.prefix(), directories))
.toArray(CompletableFuture<?>[]::new);
return CompletableFuture.allOf(futures);
}
return CompletableFuture.completedFuture(null);
});
}
}
注意事项
-
确保你已经配置了AWS凭证,可以通过:
- 环境变量
- 凭证文件 (~/.aws/credentials)
- IAM角色(如果在EC2上运行)
-
需要添加AWS SDK依赖到你的项目中(Maven示例):|
<dependency> <groupId>software.amazon.awssdk</groupId> <artifactId>s3</artifactId> <version>2.17.0</version> <!-- 使用最新版本 --> </dependency> -
对于大型S3存储桶,可能需要增加超时设置或处理分页。
-
第一个方法是同步的,适用于简单场景;第二个方法是异步的,性能更好但更复杂。
-
记得在完成后关闭客户端以释放资源。
二、豆包版
以下是一个 Java 程序,用于列出 AWS S3 存储桶中的所有目录和子目录路径。程序使用 AWS SDK for Java v2,通过递归方式遍历所有对象并提取目录结构。
S3ListDirectories.java 文件内容:
import software.amazon.awssdk.auth.credentials.ProfileCredentialsProvider;
import software.amazon.awssdk.regions.Region;
import software.amazon.awssdk.services.s3.S3Client;
import software.amazon.awssdk.services.s3.model.ListObjectsV2Request;
import software.amazon.awssdk.services.s3.model.ListObjectsV2Response;
import software.amazon.awssdk.services.s3.model.S3Object;
import java.util.*;
public class S3ListDirectories {
public static void main(String[] args) {
if (args.length != 1) {
System.out.println("请提供S3存储桶名称作为参数");
return;
}
String bucketName = args[0];
Region region = Region.US_EAST_1; // 根据实际情况修改区域
// 创建S3客户端
S3Client s3Client = S3Client.builder()
.region(region)
.credentialsProvider(ProfileCredentialsProvider.create())
.build();
// 存储所有目录路径的集合(自动去重)
Set<String> directories = new TreeSet<>();
// 列出所有对象并提取目录
listObjectsAndExtractDirectories(s3Client, bucketName, "", directories);
// 输出所有目录
System.out.println("S3存储桶 " + bucketName + " 中的目录结构:");
for (String directory : directories) {
System.out.println(directory);
}
s3Client.close();
}
private static void listObjectsAndExtractDirectories(S3Client s3Client, String bucketName, String prefix, Set<String> directories) {
ListObjectsV2Request request = ListObjectsV2Request.builder()
.bucket(bucketName)
.prefix(prefix)
.delimiter("/")
.build();
ListObjectsV2Response response;
String continuationToken = null;
do {
// 如果有继续标记,则设置它
if (continuationToken != null) {
request = request.toBuilder().continuationToken(continuationToken).build();
}
response = s3Client.listObjectsV2(request);
// 处理CommonPrefixes(目录)
if (response.commonPrefixes() != null) {
for (var commonPrefix : response.commonPrefixes()) {
String directory = commonPrefix.prefix();
directories.add(directory);
// 递归处理子目录
listObjectsAndExtractDirectories(s3Client, bucketName, directory, directories);
}
}
continuationToken = response.nextContinuationToken();
} while (response.isTruncated());
}
}
使用说明
- 依赖配置:确保在你的项目中添加 AWS SDK for Java v2 的依赖。如果你使用 Maven,可以添加以下依赖:
<dependency>
<groupId>software.amazon.awssdk</groupId>
<artifactId>s3</artifactId>
<version>2.20.95</version>
</dependency>
-
凭证配置:程序使用默认凭证提供者链,你需要配置 AWS 凭证。推荐的方法是:
- 在你的计算机上安装 AWS CLI
- 运行
aws configure命令配置访问密钥和区域
-
运行程序:编译并运行程序,将 S3 存储桶名称作为命令行参数传递:
java S3ListDirectories your-bucket-name
程序功能说明
- 程序会递归遍历指定 S3 存储桶中的所有对象和子目录
- 使用
TreeSet存储目录路径,确保自动去重并按字典序排序 - 通过
delimiter参数识别目录结构 - 处理分页结果,确保获取所有对象
- 输出格式为完整的目录路径,以斜杠结尾
工作中的版本
文件名:WarehouseImageS3Service.java
package com.fuyo.application.warehouse_image.service.extend;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import software.amazon.awssdk.auth.credentials.AwsBasicCredentials;
import software.amazon.awssdk.auth.credentials.StaticCredentialsProvider;
import software.amazon.awssdk.regions.Region;
import software.amazon.awssdk.services.s3.S3Client;
import software.amazon.awssdk.services.s3.model.ListObjectsV2Request;
import software.amazon.awssdk.services.s3.model.ListObjectsV2Response;
import java.util.Set;
import java.util.TreeSet;
/**
* 仓库过机图片S3服务类
*/
@Slf4j
@Service
public class WarehouseImageS3Service {
/**
* 同步S3文件
*/
public void syncS3Files() {
String accessKeyId = "AKIAUE5KS4KYSUUxxxxx";
String secretAccessKey = "2biqCTFqaywgExvz0I/vG2UgwkCWamOByyyyyyyy";
// 存储桶名
// String bucketName = "warehouse-pictures";
// String prefix = "";
String bucketName = "albert-test";
String prefix = "";
// 创建S3客户端
S3Client s3Client = createClient(accessKeyId, secretAccessKey, Region.CN_NORTH_1);
// 存储所有目录路径的集合(自动去重)
Set<String> directories = new TreeSet<>();
// 列出所有对象并提取目录
listObjectsAndExtractDirectories(s3Client, bucketName, prefix, directories);
s3Client.close();
// 输出所有目录
System.out.println("S3存储桶 " + bucketName + " 中的目录结构:");
for (String directory : directories) {
System.out.println(directory);
}
}
/**
* 创建S3客户端
*
* @param accessKeyId 账号
* @param secretAccessKey 密码
* @param region 区域
*/
public S3Client createClient(String accessKeyId, String secretAccessKey, Region region) {
AwsBasicCredentials credentials = AwsBasicCredentials.create(
accessKeyId,
secretAccessKey
);
// 创建S3客户端
return S3Client.builder()
.region(region)
.credentialsProvider(StaticCredentialsProvider.create(credentials))
.build();
}
private void listObjectsAndExtractDirectories(S3Client s3Client, String bucketName, String prefix, Set<String> directories) {
ListObjectsV2Request request = ListObjectsV2Request.builder()
.bucket(bucketName)
.prefix(prefix)
.delimiter("/")
.build();
ListObjectsV2Response response;
String continuationToken = null;
do {
// 如果有继续标记,则设置它
if (continuationToken != null) {
request = request.toBuilder().continuationToken(continuationToken).build();
}
response = s3Client.listObjectsV2(request);
// 处理CommonPrefixes(目录)
if (response.commonPrefixes() != null) {
for (var commonPrefix : response.commonPrefixes()) {
String directory = commonPrefix.prefix();
directories.add(directory);
// 递归处理子目录
listObjectsAndExtractDirectories(s3Client, bucketName, directory, directories);
}
}
continuationToken = response.nextContinuationToken();
} while (response.isTruncated());
}
}
输出:
S3存储桶 albert-test 中的目录结构: dg/ dg/2025/ dg/2025/06/ dg/2025/06/17/ dg/2025/06/18/ dg/2025/06/19/ nb/ nb/2025/