删除文件夹及其内容 AWS S3 java

Posted

技术标签:

【中文标题】删除文件夹及其内容 AWS S3 java【英文标题】:Delete a folder and its content AWS S3 java 【发布时间】:2017-07-15 11:58:49 【问题描述】:

是否可以使用 java sdk for aws 通过单个 api 请求删除文件夹(在 S3 存储桶中)及其所有内容。对于浏览器控制台,我们可以通过单击删除文件夹及其内容,我希望使用 API 也可以实现相同的行为。

【问题讨论】:

【参考方案1】:

S3 中没有文件夹之类的东西;文件名中只是带有斜线的文件。

浏览器控制台会将这些斜杠可视化为文件夹,但它们不是真实的。

你可以删除所有具有相同前缀的文件,但首先你需要用list_objects()查找它们,然后你可以批量删除它们。

使用 Java sdk 的代码 sn-p 请参考下面的文档

http://docs.aws.amazon.com/AmazonS3/latest/dev/DeletingMultipleObjectsUsingJava.html

【讨论】:

谢谢你的回复,我已经在使用listObject和批量删除的东西了。获取和删除是一个漫长的过程:( @MunishDhiman 这是您拥有的唯一方法,正如 AWS 文档和我的回答中明确提到的那样,S3 没有文件夹的概念,您必须自己删除每个对象。批量调用将得到优化,有助于批量删除。 我喜欢看到久经考验的真实评论“S3 中没有文件夹之类的东西”,尤其是当我提醒 AWS api 设计人员也对此感到困惑时 docs.aws.amazon.com/sdk-for-java/v1/developer-guide/…【参考方案2】:

您可以在 ListObjectsRequest 中指定 keyPrefix。

例如,考虑一个包含以下键的存储桶:

foo/bar/baz foo/bar/bash foo/bar/bang foo/boo

并且您想从 foo/bar/baz 中删除文件。

if (s3Client.doesBucketExist(bucketName)) 
        ListObjectsRequest listObjectsRequest = new ListObjectsRequest()
                .withBucketName(bucketName)
                .withPrefix("foo/bar/baz");

        ObjectListing objectListing = s3Client.listObjects(listObjectsRequest);

        while (true) 
            for (S3ObjectSummary objectSummary : objectListing.getObjectSummaries()) 
                s3Client.deleteObject(bucketName, objectSummary.getKey());
            
            if (objectListing.isTruncated()) 
                objectListing = s3Client.listNextBatchOfObjects(objectListing);
             else 
                break;
            
        
    

https://docs.aws.amazon.com/AWSJavaSDK/latest/javadoc/com/amazonaws/services/s3/model/ListObjectsRequest.html

【讨论】:

baz文件夹里面的文件被删除后怎么删除?你用s3Client.deleteObject(bucketName, "foo/bar/baz"); 吗? 请注意,这可能需要很长时间,因为您要为每个对象发送一个请求,如果您有很多文件,最好使用DeleteObjectsRequest【参考方案3】:

在 java sdk 中没有提供文件夹名称或更具体的前缀来删除文件的选项。但是可以选择提供要删除的键数组。 Click for details . 通过使用这个,我写了一个小方法来删除所有与前缀对应的文件。

private AmazonS3 s3client = <Your s3 client>;
private String bucketName = <your bucket name, can be signed or unsigned>;

public void deleteDirectory(String prefix) 
    ObjectListing objectList = this.s3client.listObjects( this.bucketName, prefix );
    List<S3ObjectSummary> objectSummeryList =  objectList.getObjectSummaries();
    String[] keysList = new String[ objectSummeryList.size() ];
    int count = 0;
    for( S3ObjectSummary summery : objectSummeryList ) 
        keysList[count++] = summery.getKey();
    
    DeleteObjectsRequest deleteObjectsRequest = new DeleteObjectsRequest( bucketName ).withKeys( keysList );
    this.s3client.deleteObjects(deleteObjectsRequest);

【讨论】:

如果您的对象在页面范围内,效果很好。否则需要在结果上全部isTruncated()/实现分页。 我还建议在尝试调用 DeleteObjectsRequest 之前检查 objectSummeryList 的大小。 如果有截断的页面将不起作用【参考方案4】:

你可以试试这个

void deleteS3Folder(String bucketName, String folderPath) 
    for (S3ObjectSummary file : s3.listObjects(bucketName, folderPath).getObjectSummaries())
        s3.deleteObject(bucketName, file.getKey());
    

【讨论】:

【参考方案5】:

您可以尝试以下方法,即使是截断的页面也会处理删除,并且它会递归删除给定目录中的所有内容:

   public Set<String> listS3DirFiles(String bucket, String dirPrefix) 
        ListObjectsV2Request s3FileReq = new ListObjectsV2Request()
                .withBucketName(bucket)
                .withPrefix(dirPrefix)
                .withDelimiter("/");

        Set<String> filesList = new HashSet<>();
        ListObjectsV2Result objectsListing;
        try 
            do 
                objectsListing = amazonS3.listObjectsV2(s3FileReq);
                objectsListing.getCommonPrefixes().forEach(folderPrefix -> 
                    filesList.add(folderPrefix);
                    Set<String> tempPrefix = listS3DirFiles(bucket, folderPrefix);
                    filesList.addAll(tempPrefix);
                );

                for (S3ObjectSummary summary: objectsListing.getObjectSummaries()) 
                    filesList.add(summary.getKey());
                

                s3FileReq.setContinuationToken(objectsListing.getNextContinuationToken());
             while(objectsListing.isTruncated());
         catch (SdkClientException e) 
            System.out.println(e.getMessage());
            throw e;
        

        return filesList;
    

    public boolean deleteDirectoryContents(String bucket, String directoryPrefix) 
        Set<String> keysSet = listS3DirFiles(bucket, directoryPrefix);

        if (keysSet.isEmpty()) 
            System.out.println("Given directory  doesn't have any file "+ directoryPrefix);
            return false;
        

        DeleteObjectsRequest deleteObjectsRequest = new DeleteObjectsRequest(bucket)
                .withKeys(keysSet.toArray(new String[0]));
        try 
            amazonS3.deleteObjects(deleteObjectsRequest);
          catch (SdkClientException e) 
            System.out.println(e.getMessage());
            throw e;
        

        return true;
    

【讨论】:

以上是关于删除文件夹及其内容 AWS S3 java的主要内容,如果未能解决你的问题,请参考以下文章

AWS lambda 函数从 S3 文件夹中删除文件

使用 AWS 开发工具包从 Amazon S3 下载文件后如何删除文件

AWS Lambda无法删除Amazon S3对象

AWS Lambda 无法删除 Amazon S3 对象

加载文件后如何清理 AWS Firehose 使用的 S3 文件?

AWS S3生命周期配置