C# AmazonS3:如何获取存储桶中的文件夹列表?

C# AmazonS3:如何获取存储桶中的文件夹列表?,c#,amazon-web-services,amazon-s3,aws-sdk,C#,Amazon Web Services,Amazon S3,Aws Sdk,我发现的都是这种方法 但我不明白如何才能只获得当前文件夹中的文件夹列表。我需要使用哪个前缀和分隔符?这可能吗?举个例子,假设我在USEast1区域中有一个名为MyBucketName的bucket,使用以下键: temp/ temp/foobar.txt temp/txt/ temp/txt/test1.txt temp/txt/test2.txt temp2/ 使用文件夹可能会让人困惑,因为S3本身并不支持层次结构——相反,它们与任何其他S3对象一样只是键。文件夹只是S3 web

我发现的都是这种方法
但我不明白如何才能只获得当前文件夹中的文件夹列表。我需要使用哪个前缀和分隔符?这可能吗?

举个例子,假设我在
USEast1
区域中有一个名为
MyBucketName
的bucket,使用以下键:

 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:存储桶中的所有文件夹

此代码从S3文档中修改为列出bucket中的所有键。下面的示例将标识以分隔符
/
结尾且也是空的所有键

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);
}
示例2:与指定前缀匹配的文件夹

通过将
Prefix
属性设置为on,可以进一步将此限制为仅检索与指定的
前缀匹配的文件夹

当应用于示例1时,我们希望得到以下输出:

temp/
temp/txt/
进一步阅读:


  • 使用
    前缀
    ,/path/to/read/
    (注意没有前导斜杠,但有一个尾随斜杠)和
    /
    分隔符
    ,您可以在
    中找到该文件夹中的所有文件夹

    通用前缀

    只有在指定分隔符时,响应才能包含
    CommonPrefixes
    。执行此操作时,
    CommonPrefixes
    包含前缀和分隔符指定的下一个字符串之间的所有键(如果有)。实际上,CommonPrefixes列出的键与
    Prefix
    指定的目录中的子目录类似。例如,如果前缀为notes/且分隔符为斜杠(/),则在notes/summer/july中,常用前缀为notes/summer/。在计算返回数时,在公共前缀中汇总的所有键都作为单个返回计数。请参阅MaxKeys


    另一种更简单的方法是使用

    Net实现了与AmazonS3和其他兼容存储解决方案配合使用的最小API

    下面的示例演示如何仅筛选出目录。这里,CommonPrefix通过ListObjects()API抽象为一个文件夹


    Anthony在这里缺少的是,文件夹不一定有与其关联的键。如果在S3中创建了一个文件,并提供了一个类似“folder/name.ext”的键,S3将显示一个“folder”文件夹,但它没有键,这意味着您无法在结果中获得它


    捕获这些文件夹的唯一方法是查看键本身,并将“/”字符的键名正则化。如果我对C#了解得多一点,我会给你写一个代码示例,但作为参考,我在另一个问题上写了一个示例。

    在我的参数中添加一个“/”分隔符对我来说很有用

    如果有人需要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)
                }
            })
        })
    }
    

    谢谢你的详细答复。当我在x.Size==1上更改x.Size==0时,此代码对我有效。但它不能识别所有文件夹,只能识别其中的一小部分。我不明白为什么会这样。我确信我的周期会一次又一次地重复直到结束。但是我不能得到所有的文件夹。原因是什么?可能与您将尺码改为1有关?”文件夹“”在此列表调用中显示为S3对象,没有内容:它们的大小应为0。如果要在没有大小的情况下找到所需的对象,您可以简单地从谓词中删除大小。如果之后仍有问题,请确保ListObjectsRequest不会对您的请求限制太多。例如,如果指定了前缀。。。在没有它的情况下测试代码,以确保它不会对您的请求限制太多。如果这不起作用,请随便问一个新问题(这个问题很清楚,我们不想把它弄得乱七八糟),举例说明你的bucket结构和你试图提出的请求。如果我试图删除大小比较,我在写x时会得到相同的结果。size==1。你能用我的结果查看我的代码吗?下面是它的外观:
    request.Delimiter
    是不必要的,可能会引起麻烦,请不要使用它。有趣的是,
    BF/Music/
    似乎被直接跳过了;你能做一个健全的检查,确保它存在于S3存储桶中吗?至于子目录,如果您不想要它们,您可以在通过正则表达式检索或匹配单个斜杠等之后进一步过滤列表。
    temp/
    temp/txt/
    
    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;
            }
        }
    }
    
    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)
                }
            })
        })
    }