2015-11-05 1128 views

回答

15

例如起见,假设我在USEast1区域称为MyBucketName水桶,使用下列按键:

temp/ 
temp/foobar.txt 
temp/txt/ 
temp/txt/test1.txt 
temp/txt/test2.txt 
temp2/ 

使用文件夹可能会造成混淆,因为S3本身不支持层次结构 - - 相反,这些只是像任何其他S3对象一样的键。文件夹只是S3 Web控制台中提供的一种抽象,可以更轻松地浏览存储桶。因此,当我们以编程方式工作时,我们希望找到与“文件夹”(分隔符'/',size = 0)尺寸匹配的键,因为它们很可能是由S3控制台呈现给我们的'文件夹'。

请注意这两个示例:我正在使用AWSSDK.S3版本3.1 NuGet软件包。

实施例1:在水桶

该代码从this basic example修改S3文档中列出在一个桶中的所有键的所有文件夹。下面的示例将标识以分隔符字符/结尾的所有密钥,并且它们也是空的。

IAmazonS3 client; 
using (client = new AmazonS3Client(Amazon.RegionEndpoint.USEast1)) 
{ 
    // Build your request to list objects in the bucket 
    ListObjectsRequest request = new ListObjectsRequest 
    { 
     BucketName = "MyBucketName" 
    }; 

    do 
    { 
     // Build your call out to S3 and store the response 
     ListObjectsResponse response = client.ListObjects(request); 

     // Filter through the response to find keys that: 
     // - end with the delimiter character '/' 
     // - are empty. 
     IEnumerable<S3Object> folders = response.S3Objects.Where(x => 
      x.Key.EndsWith(@"/") && x.Size == 0); 

     // Do something with your output keys. For this example, we write to the console. 
     folders.ToList().ForEach(x => System.Console.WriteLine(x.Key)); 

     // If the response is truncated, we'll make another request 
     // and pull the next batch of keys 
     if (response.IsTruncated) 
     { 
      request.Marker = response.NextMarker; 
     } 
     else 
     { 
      request = null; 
     } 
    } while (request != null); 
} 

预计输出到控制台:

temp/ 
temp/txt/ 
temp2/ 

例2:文件夹匹配指定前缀的

你可以进一步限制这仅通过设置Prefix检索匹配指定Prefix文件夹物业ListObjectsRequest

ListObjectsRequest request = new ListObjectsRequest 
    { 
     BucketName = "MyBucketName", 
     Prefix = "temp/" 
    }; 

当施加到实施例1,我们希望下面的输出:

temp/ 
temp/txt/ 

进一步阅读:

+0

谢谢你的详细回复。当我在x.Size == 1上更改x.Size == 0时,此代码适用于我。但它不能识别所有文件夹,只能识别它们中的一小部分。我无法理解为什么会发生这种情况。我正是这样,我的周期一遍又一遍,直到它结束。但我无法获得所有的文件夹。可能是什么原因? – neustart47

+1

也许与您相关将尺寸更改为1?在这个列表调用中,'文件夹'作为没有内容的S3对象呈现:它们应该是大小0.如果没有它,您可以简单地从谓词中移除大小。 –

+2

如果您在此之后仍然遇到问题,请确保您的ListObjectsRequest不会过多地限制您的请求。例如,如果您指定了一个前缀...在没有它的情况下测试您的代码,以确保它不会过多地限制您的请求。如果这不起作用,可以随时提出一个新问题(这个问题非常清楚,我们不想把它弄得混乱),举例说明了你的存储桶的结构和你试图制作的请求。 –

3

使用的the/path/to/read/prefix(注意,没有斜线,但有结尾的斜线),以及/delimiter,你会发现里面<CommonPrefixes>该文件夹内的所有文件夹。

CommonPrefixes

的响应可以包含CommonPrefixes只有在指定的分隔符。当您这样做时,CommonPrefixes包含Prefix和由定界符指定的字符串的下一次出现之间的所有键(如果有的话)。实际上,CommonPrefixes列出了在Prefix指定的目录中充当子目录的密钥。例如,如果前缀是notes /而分隔符是斜杠(/),则在notes/summer/july中,常用前缀是notes/summer /。计算退货数量时,所有在一个通用前缀中汇总的密钥计为一次返回。见MaxKeys。

http://docs.aws.amazon.com/AmazonS3/latest/API/RESTBucketGET.html

4

或者另一种更简单的方法是使用https://github.com/minio/minio-dotnet

Minio的.Net实现最小的API与Amazon S3和其他兼容的存储解决方案的工作。

以下示例显示了如何只过滤出目录。这里CommonPrefix通过ListObjects()API被抽象为一个文件夹。

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 
using System.Threading.Tasks; 

using Minio; 
using Minio.Xml; 

namespace Minio.Examples 
{ 
    class ListObjects 
    { 
     static int Main(string[] args) 
     { 
      var client = new MinioClient("https://s3.amazonaws.com", "ACCESSKEY", "SECRETKEY"); 

      var items = client.ListObjects("bucket"); 

      foreach (Item item in items) 
      { 
       if (item.IsDir) 
       { 
        Console.Out.WriteLine("{0}", item.Key); 
       } 
      } 
      return 0; 
     } 
    } 
} 
2

安东尼在这里丢失的是一个文件夹不一定有一个关联它的关键。如果一个文件是在S3中创建的,并且给出了一个像“folder/name.ext”这样的密钥,那么S3会显示一个“文件夹”文件夹,但它没有密钥,这意味着你没有得到它的结果。

捕获这些文件夹的唯一方法是查看这些键本身,并将“/”字符的键名正则表达。如果我知道C#更好一点,我会给你写一个代码示例,但是参考这里是一个python example我写了另一个问题。