在 amazon s3 java 中删除文件、目录和存储桶

Posted

技术标签:

【中文标题】在 amazon s3 java 中删除文件、目录和存储桶【英文标题】:Delete files, directories and buckets in amazon s3 java 【发布时间】:2011-12-07 11:22:07 【问题描述】:

我想知道如何做到这一点。我查看了 sdk 文档并有一些示例,但对语法的一般情况感到困惑。

如果我想删除一个文件,我假设我使用deleteObject(path, key)。然而,什么是“钥匙”?

另外你如何删除一个目录?我似乎找不到这样做的方法。

【问题讨论】:

你找到删除文件夹的方法了吗?? 只能删除空目录。因此,首先删除内容,然后使用 s3Client.deleteObject(bucket name, folderName) 删除目录。 Refer this 【参考方案1】:

S3 中的“键”类似于文件路径:

http://bucket.s3.amazonaws.com/some/path/to/use

... 位于名为 bucket 的存储桶中,并且具有 some/path/to/use 的键。

它实际上不是路径,因为没有文件夹。 S3 密钥只是一个大目录(整个存储桶)中文件的文件名。 S3 密钥可以包含/,但没有特殊含义,除非您设置了delimiter argument with listing a bucket。

换句话说,拥有一个名为some/object 的对象并不能告诉您有关some 对象的任何信息(它可能存在也可能不存在——这两个对象不相关)。

但是,您可以请求带有特定前缀的密钥,所以我可以说“给我所有以 some/path/to/ 开头的密钥,它将返回 some/path/to/use。看起来像“列出目录”,但实际上只是在询问对于以特定字符串开头的文件。

我可以像这样轻松地命名:

somepathtousea
somepathtouseb

然后说“给我所有以somepathtouse 开头的东西”(它会说somepathtouseasomepathtouseb)。

注意:S3 URL 来自 several forms:

http://s3.amazonaws.com/bucket/key
http://bucket.s3.amazonaws.com/key
http://bucket/key (where bucket is a DNS CNAME record pointing to bucket.s3.amazonaws.com)

编辑:

我查看了the JavaDocs,这是我看到的函数签名(AmazonS3Client):

public void deleteObject(java.lang.String bucketName,
                         java.lang.String key)
                  throws AmazonClientException,
                         AmazonServiceException

再次编辑:

文件夹现在确实存在,作为内容类型为application/x-directory 和以/ 结尾的键的零长度对象:

$ AWS_PROFILE=prod aws s3api head-object --bucket example-bucket --key example-directory/

    "AcceptRanges": "bytes",
    "LastModified": "Mon, 29 Apr 2019 14:59:36 GMT",
    "ContentLength": 0,
    "ETag": "\"d41d8cd98f00b204e9800998ecf8427e\"",
    "ContentType": "application/x-directory",
    "ServerSideEncryption": "AES256",
    "Metadata": 

这仍然只是惯例,没有什么可以阻止您拥有以 / 结尾的文件或不存在的“文件夹”内的文件。

【讨论】:

所以语法应该是deleteObject(bucketName, path)? @cfarm54 - 除了键不是路径。它们的 key-bucket 关系更像.. key 是一个文件名(可能包含/),而 bucket 是一个大文件夹。 谢谢,请问如何删除目录和存储桶? @cfarm54 - 查看documentation for AmazonS3Client。 deleteBucket(String bucketName) 删除整个存储桶。 S3 has no method to delete keys with a common prefix。您必须列出它们 (listObjects(String bucketName, String prefix)),然后单独删除它们。 啊,我明白了,如果您将 delimiter 设置为 /,ListBucket 会将键中的 / 视为目录分隔符:docs.aws.amazon.com/AmazonS3/latest/API/v2-RESTBucketGET.html 我假设 awscli 默认设置了这个.【参考方案2】:

这行代码适用于我的情况,keyName 是文件名:

s3Client.deleteObject(new DeleteObjectRequest(bucketName, keyName));

【讨论】:

【参考方案3】:

批量删除 S3 存储桶中的对象列表:

public void deleteObjects(String bucketName, List<String> keys) 

    List<KeyVersion> bulk = new ArrayList<>();
    for (int i = 0; i < keys.size(); i++) 
        bulk.add(new KeyVersion(keys.get(i)));
        if (i % 100 == 0) 
            try 
                s3Client.deleteObjects(new DeleteObjectsRequest(bucketName).withKeys(bulk));
             catch (Exception e) 
                System.err.println(e.getErrorMessage());
            
            bulk.clear();
        
    
    if (bulk.size() > 0) 
        try 
            s3Client.deleteObjects(new DeleteObjectsRequest(bucketName).withKeys(bulk));
         catch (Exception e) 
            System.err.println(e.getErrorMessage());
        
    

来源:http://codeflex.co/delete-objects-from-amazon-s3-bucket-using-aws-sdk-for-java/

【讨论】:

【参考方案4】:

ListObjectsV2Result 对我有用。尝试一次。

private void deleteObjectsInFolder() 
    try 
        ListObjectsV2Result result;
        do 
            String folderPath =   " ";



            result = s3.listObjectsV2(Constants.BUCKET_NAME, folderPath);

            Log.e("count:", result.getKeyCount() + "");

            if (result.getKeyCount() != 0) 

                for (S3ObjectSummary objectSummary :
                        result.getObjectSummaries()) 
                    s3.deleteObject(Constants.BUCKET_NAME, objectSummary.getKey());
                

            


            System.out.println("Next Continuation Token : " + result.getNextContinuationToken());
         while (result.isTruncated() == true);

     catch (AmazonServiceException ase) 
        System.out.println("Caught an AmazonServiceException, " +
                "which means your request made it " +
                "to Amazon S3, but was rejected with an error response " +
                "for some reason.");
        System.out.println("Error Message:    " + ase.getMessage());
        System.out.println("HTTP Status Code: " + ase.getStatusCode());
        System.out.println("AWS Error Code:   " + ase.getErrorCode());
        System.out.println("Error Type:       " + ase.getErrorType());
        System.out.println("Request ID:       " + ase.getRequestId());
     catch (AmazonClientException ace) 
        System.out.println("Caught an AmazonClientException, " +
                "which means the client encountered " +
                "an internal error while trying to communicate" +
                " with S3, " +
                "such as not being able to access the network.");
        System.out.println("Error Message: " + ace.getMessage());
    

【讨论】:

【参考方案5】:

关于在亚马逊 S3 java 中删除文件、目录和存储桶的问题,我想提供删除非空 S3 存储桶的代码 (AWS Reference):

 public void deleteBucket(final String bucketName) 

        final AmazonS3 s3 = AmazonS3ClientBuilder.defaultClient();

        try 
            ObjectListing objectListing = s3.listObjects(bucketName);
            while (true) 
                for (Iterator<?> iterator = objectListing.getObjectSummaries().iterator(); iterator.hasNext(); ) 
                    S3ObjectSummary summary = (S3ObjectSummary) iterator.next();
                    s3.deleteObject(bucketName, summary.getKey());
                

                if (objectListing.isTruncated()) 
                    objectListing = s3.listNextBatchOfObjects(objectListing);
                 else 
                    break;
                
            

            VersionListing versionListing = s3.listVersions(new ListVersionsRequest().withBucketName(bucketName));
            while (true) 
                for (Iterator<?> iterator = versionListing.getVersionSummaries().iterator(); iterator.hasNext(); ) 
                    S3VersionSummary vs = (S3VersionSummary) iterator.next();
                    s3.deleteVersion(bucketName, vs.getKey(), vs.getVersionId());
                

                if (versionListing.isTruncated()) 
                    versionListing = s3.listNextBatchOfVersions(versionListing);
                 else 
                    break;
                
            

            s3.deleteBucket(bucketName);
         catch (AmazonServiceException e) 
            System.err.println(e.getErrorMessage());
        
    

【讨论】:

【参考方案6】:

/*这是适合我的解决方案。这里 Bucket_Name 是我在 S3 上的存储桶名称,key 是 Bucket_Name 下的路径。所以,如果 S3 上的绝对路径是:

s3://my_bucket/Path/to/my/folder

那么,下面的代码应该可以工作了。 */


    String Bucket_Name = "my_bucket";
    String key = "Path/to/my/folder";   
    ObjectListing objects = s3Client.listObjects(BUCKET_NAME, key);
        for (S3ObjectSummary objectSummary : objects.getObjectSummaries()) 
            
            s3Client.deleteObject(BUCKET_NAME, objectSummary.getKey());
                       

【讨论】:

欢迎来到 SO。您还没有解决“什么是关键”的问题。您正在提供代码,但它需要一些解释以使其对其他有问题的用户具有更高的价值。 @ShawnMehan:感谢您的反馈,我会更新我的答案。【参考方案7】:

为我工作,小心截断!

    long start = System.currentTimeMillis();
    long totalSize = 0;
    int totalItems = 0;

    String key ="path/to/folder/"
    String bucket = "my-bucket"

    final ListObjectsRequest listObjectsRequest = new ListObjectsRequest().withBucketName(bucketName).withPrefix(key);

    ObjectListing objects = s3.listObjects(listObjectsRequest);
    do 
        for (S3ObjectSummary objectSummary : objects.getObjectSummaries()) 
            totalSize += objectSummary.getSize();
            totalItems++;
            s3.deleteObject(bucketName, objectSummary.getKey());
        
        objects = s3.listNextBatchOfObjects(objects);
     while (objects.isTruncated());

    long stop = System.currentTimeMillis();

    LOG.trace("User  had  items with  Kb, took  ms to delete", user.getName(), totalItems, totalSize / 1024, stop
            - start);

【讨论】:

你测试过这段代码吗?因为我会说,在“截断”的情况下,此代码不会删除listNextBatchOfObjects 读取的最后一批文件。另一件事是我想知道亚马逊是否会在同时删除它们的同时正确处理批量列出的对象? 正如@MJar 所说,这段代码很危险,不会按预期工作。 你需要在 isTruncated 之后分配新的值。像这样的东西: while (objects.isTruncated() &amp;&amp; (objects = s3.listNextBatchOfObjects(objects)) != null);【参考方案8】:

这段代码对我有用。 folderPath 类似于“topDir/secondDir/”

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

【讨论】:

您能否提供更多信息,说明为什么此代码不适合您?我从运行代码中复制了它。 小心 getObjectSummaries 会返回一个截断的列表! 有人知道如何用 V2 做到这一点吗?【参考方案9】:

您可能想查看example,以快速了解如何从 S3 中删除对象。

delete 的语法实际上是 deleteObject( bucketName, key ) 其中 bucketName 是您放置文件的存储桶,而 key 是您要在存储桶中删除的文件的名称。

将存储桶想象成您的硬盘驱动器,如 C:\ 、 D:\ 等。key 是您要删除的文件的绝对路径名。

【讨论】:

以上是关于在 amazon s3 java 中删除文件、目录和存储桶的主要内容,如果未能解决你的问题,请参考以下文章

Amazon S3 删除标记

如何判断我的文件是不是已使用他们的 SDK 从 Amazon S3 中成功删除?

Amazon S3 将目录复制到另一个目录

如何(批量)删除Amazon S3存储桶中几百个文件的列表

使用 PHP 开发工具包删除 Amazon S3 中的版本控制文件

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