web-dev-qa-db-ja.com

Amazon S3:バケット内のフォルダーのリストを取得する方法は?

私が見つけたのは、このメソッドです GET Bucket しかし、現在のフォルダー内のフォルダーのリストのみを取得する方法がわかりません。どの接頭辞と区切り記号を使用する必要がありますか?それは可能ですか?

7
neustart47

例として、USEast1領域にMyBucketNameという名前のバケットがあり、次のキーがあるとします。

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

S3は階層構造をネイティブにサポートしていないため、フォルダーの操作は混乱を招く可能性があります。むしろ、これらは他のS3オブジェクトと同様に単なるキーです。フォルダーは、S3 Webコンソールで利用できる抽象化であり、バケットのナビゲートを容易にします。したがって、プログラムで作業しているときは、S3コンソールによって表示される「フォルダー」である可能性が高いため、「フォルダー」(区切り文字「/」、サイズ= 0)の寸法に一致するキーを見つけたいと思います。

両方の例の注意:AWSSDK.S3バージョン3.1 NuGetパッケージを使用しています

例1:バケット内のすべてのフォルダー

このコードは、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:指定されたプレフィックスに一致するフォルダー

ListObjectsRequestPrefixプロパティを設定することで、指定したPrefixに一致するフォルダのみを取得するようにこれをさらに制限できます。

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

例1に適用すると、次の出力が期待されます。

temp/
temp/txt/

さらに読む:

20
Anthony Neace

the/path/to/read/prefixを使用します(no先頭のスラッシュがありますが、isa末尾のスラッシュ)、および/delimiterの場合、<CommonPrefixes>内のそのフォルダー内のすべてのフォルダーが見つかります。

CommonPrefixes

区切り文字を指定した場合にのみ、応答にCommonPrefixesを含めることができます。その場合、CommonPrefixesには、プレフィックスと区切り文字で指定された文字列の次の出現との間のすべてのキー(存在する場合)が含まれます。実際、CommonPrefixesは、Prefixで指定されたディレクトリのサブディレクトリのように機能するキーをリストします。たとえば、プレフィックスがnotes /で、区切り文字がスラッシュ(/)の場合、notes/summer/julyでは、一般的なプレフィックスはnotes/summer /です。共通のプレフィックスにまとめられたすべてのキーは、リターン数を計算するときに単一のリターンとしてカウントされます。 MaxKeysを参照してください。

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

7

あるいは、別のより簡単なアプローチは https://github.com/minio/minio-dotnet を使用することです

Minio .Netは、AmazonS3およびその他の互換性のあるストレージソリューションと連携するための最小限のAPIを実装しています。

次の例は、ディレクトリのみを除外する方法を示しています。ここで、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;
        }
    }
}
5
Harshavardhana

Anthonyがここで欠けているのは、フォルダーに関連付けられたキーが必ずしもあるとは限らないことです。ファイルがS3で作成され、「folder/name.ext」のようなキーが与えられた場合、S3は「folder」フォルダーを表示しますが、キーがないため、結果に表示されません。

これらのフォルダをキャッチする唯一の方法は、キー自体を調べて、「/」文字のキー名を正規表現することです。 C#をもう少しよく知っていれば、コードサンプルを作成しますが、参考のために、ここに pythonの例 別の質問を作成しました。

3
Nathan Hazzard

パラメータに「/」の区切り文字を追加すると、うまくいきました。

誰かがNodeJSソリューションを必要とする場合、これは私が使用したものです:

listdelim: function (path) {
    const params = {
        Bucket: process.env['bucket'],
        MaxKeys: 1000,
        Prefix: path,
        Delimiter: '/'
    }
    return new Promise((resolve, reject) => {
        s3.listObjectsV2(params, function (err, data) {
            if (err) {
                console.log(err, err.stack)
                reject(err)
            } else {
                resolve(data)
            }
        })
    })
}
0
Brett Schmidt