【问题标题】:Amazon S3 Creating Folder through .NET SDK vs through Management ConsoleAmazon S3 通过 .NET SDK 与通过管理控制台创建文件夹
【发布时间】:2012-04-14 05:43:50
【问题描述】:

我正在尝试确定我的 Amazon S3 存储桶中是否存在文件夹,如果不存在,我想创建它。

目前我可以使用 .NET SDK 创建文件夹,如下所示:

        public void CreateFolder(string bucketName, string folderName)
    {
        var folderKey = folderName + "/"; //end the folder name with "/"

        var request = new PutObjectRequest();

        request.WithBucketName(bucketName);

        request.StorageClass = S3StorageClass.Standard;
        request.ServerSideEncryptionMethod = ServerSideEncryptionMethod.None;

        //request.CannedACL = S3CannedACL.BucketOwnerFullControl;

        request.WithKey(folderKey);

        request.WithContentBody(string.Empty);

        S3Response response = m_S3Client.PutObject(request);

    }

现在,当我尝试使用此代码查看文件夹是否存在时:

        public bool DoesFolderExist(string key, string bucketName)
    {
        try
        {
            S3Response response = m_S3Client.GetObjectMetadata(new GetObjectMetadataRequest()
               .WithBucketName(bucketName)
               .WithKey(key));

            return true;
        }
        catch (Amazon.S3.AmazonS3Exception ex)
        {
            if (ex.StatusCode == System.Net.HttpStatusCode.NotFound)
                return false;

            //status wasn't not found, so throw the exception
            throw;
        }
    }

找不到文件夹。奇怪的是,如果我使用 AWS 管理控制台创建文件夹,'DoesFolderExist' 方法可以看到它。

我不确定这是否是 ACL/IAM 问题,但不确定如何解决。

【问题讨论】:

    标签: c# .net amazon-s3 amazon-web-services


    【解决方案1】:

    您的代码实际上对我有用,但您需要注意一些事项。

    据我了解,Amazon S3 没有文件夹的概念,但个别客户端可能会像显示 S3 对象一样显示它们。因此,如果您创建一个名为 A/B 的对象,那么客户端可能会将其显示为好像它是一个名为 B 的对象,位于名为 A 的文件夹中。这很直观,似乎已成为标准,但不会出现模拟空文件夹有一个标准。

    例如,我使用您的方法创建了一个名为 Test 的文件夹,然后实际上最终创建了一个名为 Test/ 的对象。但是我在 AWS Explorer 中创建了一个名为 Test2 的文件夹(即 Visual Studio 的插件),它最终创建了一个名为 Test2/Test2_$folder$ 的对象 (AWS Explorer 会将 Test 和 Test2 都显示为文件夹)

    这意味着您不需要需要在使用“文件夹”之前创建它,这可能意味着您不需要DoesFolderExist 方法。

    正如我提到的,我尝试了您的代码,它可以工作并找到它创建的 Test 文件夹,但是必须调整密钥才能找到 AWS Explorer 创建的文件夹,即

    DoesFolderExist("Test/"               , bucketName);  // Returns true
    DoesFolderExist("Test2/"              , bucketName);  // Returns false
    DoesFolderExist("Test2/Test2_$folder$", bucketName);  // Returns true
    

    因此,如果您仍然想要一个 DoesFolderExist 方法,那么只查找以 folderName + "/" 开头的任何对象可能会更安全,例如

    ListObjectsRequest request = new ListObjectsRequest();
    request.BucketName = bucketName ;
    request.WithPrefix(folderName + "/");
    request.MaxKeys = 1;
    
    using (ListObjectsResponse response = m_S3Client.ListObjects(request))
    {
        return (response.S3Objects.Count > 0);
    }
    

    【讨论】:

      【解决方案2】:

      刚刚将上述代码重构为使用 AWS .Net SDK 版本 2 的异步方法:

      public async Task CreateFoldersAsync(string bucketName, string path)
          {
              path = path.EnsureEndsWith('/');
      
              IAmazonS3 client =
                  new AmazonS3Client(YOUR.AccessKeyId, YOUR.SecretAccessKey,
                  RegionEndpoint.EUWest1);
      
              var findFolderRequest = new ListObjectsV2Request();
              findFolderRequest.BucketName = bucketName;
              findFolderRequest.Prefix = path;
              findFolderRequest.MaxKeys = 1;
      
              ListObjectsV2Response findFolderResponse = 
                 await client.ListObjectsV2Async(findFolderRequest);
      
      
              if (findFolderResponse.S3Objects.Any())
              {
                  return;
              }
              
              PutObjectRequest request = new PutObjectRequest()
              {
                  BucketName = bucketName,
                  StorageClass = S3StorageClass.Standard,
                  ServerSideEncryptionMethod = ServerSideEncryptionMethod.None,
                  Key = path, 
                  ContentBody = string.Empty
              };
      
              // add try catch in case you have exceptions shield/handling here 
              PutObjectResponse response = await client.PutObjectAsync(request);
          }
      

      【讨论】:

        【解决方案3】:
                ListObjectsRequest findFolderRequest = new ListObjectsRequest();
                findFolderRequest.BucketName = bucketName;
                findFolderRequest.Prefix = path;
                ListObjectsResponse findFolderResponse = s3Client.ListObjects(findFolderRequest);
                Boolean folderExists = findFolderResponse.S3Objects.Any();
        

        路径可以类似于“images/40/”。 使用上面的代码可以检查bucket下是否存在所谓的“images/40/”文件夹。

        但是 Amazon S3 数据模型没有文件夹的概念。当您尝试将图像或文件复制到某个路径时,如果这个所谓的文件夹不存在,它将作为该文件或图像的键名的一部分自动创建。因此,您实际上不需要检查该文件夹是否存在。

        来自 docs.aws.amazon.com 的非常重要的信息:Amazon S3 数据模型是一种扁平结构:您创建一个存储桶,该存储桶存储对象。没有子桶或子文件夹的层次结构;但是,您可以像 Amazon S3 控制台那样使用键名前缀和分隔符来推断逻辑层次结构。

        http://docs.aws.amazon.com/AmazonS3/latest/dev/UsingMetadata.html

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2012-08-30
          • 1970-01-01
          • 1970-01-01
          • 2022-12-03
          • 2014-04-17
          • 2019-07-30
          • 1970-01-01
          相关资源
          最近更新 更多