不灭的火

革命尚未成功,同志仍须努力下载JDK17

作者:AlbertWen  添加时间:2025-06-18 15:03:11  修改时间:2025-06-19 09:15:56  分类:07.Java框架/系统  编辑

一、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);
                });
    }
}

注意事项

  1. 确保你已经配置了AWS凭证,可以通过:

    • 环境变量
    • 凭证文件 (~/.aws/credentials)
    • IAM角色(如果在EC2上运行)
  2. 需要添加AWS SDK依赖到你的项目中(Maven示例):|
     

    <dependency>
        <groupId>software.amazon.awssdk</groupId>
        <artifactId>s3</artifactId>
        <version>2.17.0</version> <!-- 使用最新版本 -->
    </dependency>

     

  3. 对于大型S3存储桶,可能需要增加超时设置或处理分页。

  4. 第一个方法是同步的,适用于简单场景;第二个方法是异步的,性能更好但更复杂。

  5. 记得在完成后关闭客户端以释放资源。

 


二、豆包版

以下是一个 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());
    }
}    

使用说明

  1. 依赖配置:确保在你的项目中添加 AWS SDK for Java v2 的依赖。如果你使用 Maven,可以添加以下依赖:
<dependency>
    <groupId>software.amazon.awssdk</groupId>
    <artifactId>s3</artifactId>
    <version>2.20.95</version>
</dependency>
  1. 凭证配置:程序使用默认凭证提供者链,你需要配置 AWS 凭证。推荐的方法是:

    • 在你的计算机上安装 AWS CLI
    • 运行aws configure命令配置访问密钥和区域
  2. 运行程序:编译并运行程序,将 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/