一、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/