2015-11-05 1121 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我寫了另一個問題。