【问题标题】:Checking if a blob exists in Azure Storage检查 Azure 存储中是否存在 blob
【发布时间】:2011-02-08 05:34:55
【问题描述】:

我有一个非常简单的问题(我希望如此!) - 我只是想找出一个 blob(具有我已定义的名称)是否存在于特定容器中。如果它存在,我会下载它,如果它不存在,我会做其他事情。

我已经在 intertubes 上进行了一些搜索,显然曾经有一个名为 DoesExist 或类似的函数......但与许多 Azure API 一样,这似乎不再存在(或者如果它是,有一个伪装得很巧妙的名字)。

【问题讨论】:

  • 谢谢大家。由于我正在使用 StorageClient(并且希望通过该库保持我的所有 Azure 存储访问权限),我使用了 smarx 建议的 FetchAttributes-and-check-for-exceptions 方法。它确实“感觉”有点不对劲,因为我不喜欢将异常作为我的业务逻辑的正常部分抛出 - 但希望这可以在未来的 StorageClient 版本中修复:)

标签: c# azure azure-blob-storage


【解决方案1】:

新 API 具有 .Exists() 函数调用。只要确保您使用GetBlockBlobReference,它不会执行对服务器的调用。它使函数变得简单:

public static bool BlobExistsOnCloud(CloudBlobClient client, 
    string containerName, string key)
{
     return client.GetContainerReference(containerName)
                  .GetBlockBlobReference(key)
                  .Exists();  
}

【讨论】:

  • 有.. 一个... python 版本吗?
  • 想知道检查 blob 是否存在需要支付什么费用?与尝试下载 blob 相比,此 defo 似乎是一种更好的方法。
  • @anpatel,python 版本:len(blob_service.list_blobs(container_name, file_name)) > 0
  • 你可以更新你的答案,应该安装哪个 nuget 包
  • 注意:从 Microsoft.WindowsAzure.Storage 版本 8.1.4.0 (.Net Framework v4.6.2) 开始, Exists() 方法不存在,取而代之的是 ExistsAsync()为 .NetCore 项目安装
【解决方案2】:

注意:这个答案现在已经过时了。请参阅 Richard 的回答,了解检查是否存在的简单方法

不,您并没有遗漏一些简单的东西……我们很好地将这个方法隐藏在新的 StorageClient 库中。 :)

我刚刚写了一篇博文来回答你的问题:http://blog.smarx.com/posts/testing-existence-of-a-windows-azure-blob

简短的回答是:使用 CloudBlob.FetchAttributes(),它针对 blob 执行 HEAD 请求。

【讨论】:

  • FetchAttributes() 如果文件尚未完全提交,即仅由未提交的块组成,则需要很长时间才能运行(至少在开发存储中)。
  • 如果您要按照 OP 的意图获取 blob,为什么不立即尝试下载内容呢?如果它不存在,它将像 FetchAttributes 一样抛出。先做这个检查只是一个额外的要求,还是我遗漏了什么?
  • Marnix 提出了一个很好的观点。如果您仍然要下载它,请尝试下载它。
  • @Marnix:如果你调用OpenRead 之类的东西,它不会抛出或返回空流或类似的东西。当您开始从它下载时,您只会收到错误。在一个地方处理这一切要容易得多:)
  • @Porges:设计云应用程序就是“为失败而设计”。有很多讨论如何正确处理这种情况。但总的来说 - 我也会去下载它,然后处理丢失的 Blob 错误。不仅如此,如果我要检查每个 blob 是否存在,我会增加存储事务的数量,从而增加我的账单。您仍然可以在一个地方处理异常/错误。
【解决方案3】:

你需要捕获一个异常来测试它是否存在,这似乎很蹩脚。

public static bool Exists(this CloudBlob blob)
{
    try
    {
        blob.FetchAttributes();
        return true;
    }
    catch (StorageClientException e)
    {
        if (e.ErrorCode == StorageErrorCode.ResourceNotFound)
        {
            return false;
        }
        else
        {
            throw;
        }
    }
}

【讨论】:

    【解决方案4】:

    如果 blob 是公开的,您当然可以只发送一个 HTTP HEAD 请求——来自任何知道如何做的语言/环境/平台——然后检查响应。

    核心 Azure API 是基于 RESTful XML 的 HTTP 接口。 StorageClient 库是围绕它们的许多可能的包装器之一。这是 Sriram Krishnan 在 Python 中所做的另一个:

    http://www.sriramkrishnan.com/blog/2008/11/python-wrapper-for-windows-azure.html

    它还展示了如何在 HTTP 级别进行身份验证。

    我在 C# 中为自己做过类似的事情,因为我更喜欢通过 HTTP/REST 的镜头而不是通过 StorageClient 库的镜头来看待 Azure。很长一段时间以来,我什至都懒得实现 ExistsBlob 方法。我所有的 blob 都是公开的,做 HTTP HEAD 很简单。

    【讨论】:

      【解决方案5】:

      新的 Windows Azure 存储库已经包含 Exist() 方法。 它在 Microsoft.WindowsAzure.Storage.dll 中。

      作为 NuGet 包提供
      创建者:微软
      ID:WindowsAzure.Storage
      版本:2.0.5.1

      See also msdn

      【讨论】:

        【解决方案6】:

        我就是这样做的。为需要的人展示完整的代码。

                // Parse the connection string and return a reference to the storage account.
                CloudStorageAccount storageAccount = CloudStorageAccount.Parse(CloudConfigurationManager.GetSetting("AzureBlobConnectionString"));
        
                CloudBlobClient blobClient = storageAccount.CreateCloudBlobClient();
        
                // Retrieve reference to a previously created container.
                CloudBlobContainer container = blobClient.GetContainerReference("ContainerName");
        
                // Retrieve reference to a blob named "test.csv"
                CloudBlockBlob blockBlob = container.GetBlockBlobReference("test.csv");
        
                if (blockBlob.Exists())
                {
                  //Do your logic here.
                }
        

        【讨论】:

          【解决方案7】:

          如果您不喜欢其他解决方案,这里有一个不同的解决方案:

          我使用的是 12.4.1 版的 Azure.Storage.Blobs NuGet 包。

          我得到一个 Azure.Pageable 对象,它是容器中所有 blob 的列表。然后,我检查 BlobItem 的名称是否等于容器内每个 blob 的 Name 属性,使用 LINQ。 (当然,如果一切都有效)

          using Azure.Storage.Blobs;
          using Azure.Storage.Blobs.Models;
          using System.Linq;
          using System.Text.RegularExpressions;
          
          public class AzureBlobStorage
          {
              private BlobServiceClient _blobServiceClient;
          
              public AzureBlobStorage(string connectionString)
              {
                  this.ConnectionString = connectionString;
                  _blobServiceClient = new BlobServiceClient(this.ConnectionString);
              }
          
              public bool IsContainerNameValid(string name)
              {
                  return Regex.IsMatch(name, "^[a-z0-9](?!.*--)[a-z0-9-]{1,61}[a-z0-9]$", RegexOptions.Singleline | RegexOptions.CultureInvariant);
              }
          
              public bool ContainerExists(string name)
              {
                  return (IsContainerNameValid(name) ? _blobServiceClient.GetBlobContainerClient(name).Exists() : false);
              }
          
              public Azure.Pageable<BlobItem> GetBlobs(string containerName, string prefix = null)
              {
                  try
                  {
                      return (ContainerExists(containerName) ? 
                          _blobServiceClient.GetBlobContainerClient(containerName).GetBlobs(BlobTraits.All, BlobStates.All, prefix, default(System.Threading.CancellationToken)) 
                          : null);
                  }
                  catch
                  {
                      throw;
                  }
              }
          
              public bool BlobExists(string containerName, string blobName)
              {
                  try
                  {
                      return (from b in GetBlobs(containerName)
                               where b.Name == blobName
                               select b).FirstOrDefault() != null;
                  }
                  catch
                  {
                      throw;
                  }
              }
          }
          

          希望这对将来的某人有所帮助。

          【讨论】:

            【解决方案8】:

            如果您不喜欢使用异常方法,那么 judell 建议的基本 c# 版本如下。请注意,您确实也应该处理其他可能的响应。

            HttpWebRequest myReq = (HttpWebRequest)WebRequest.Create(url);
            myReq.Method = "HEAD";
            HttpWebResponse myResp = (HttpWebResponse)myReq.GetResponse();
            if (myResp.StatusCode == HttpStatusCode.OK)
            {
                return true;
            }
            else
            {
                return false;
            }
            

            【讨论】:

            • HttpWebRequest.GetResponse 如果出现 404 则抛出异常。所以我看不出您的代码将如何规避处理异常的需要?
            • 公平点。在我看来,GetResponse() 在那一点上抛出了垃圾!我希望它返回 404,因为这是响应!!!
            【解决方案9】:

            如果您的 blob 是公开的并且您只需要元数据:

                    HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
                    request.Method = "HEAD";
                    string code = "";
                    try
                    {
                        HttpWebResponse response = (HttpWebResponse)request.GetResponse();
                        code = response.StatusCode.ToString();
                    }
                    catch 
                    {
                    }
            
                    return code; // if "OK" blob exists
            

            【讨论】:

              【解决方案10】:

              使用更新的 SDK,一旦您拥有 CloudBlobReference,您就可以在您的引用上调用 Exists()。

              http://msdn.microsoft.com/en-us/library/microsoft.windowsazure.storage.blob.cloudblockblob.exists.aspx

              【讨论】:

                【解决方案11】:

                虽然这里的大多数答案在技术上都是正确的,但大多数代码示例都在进行同步/阻塞调用。除非您受非常旧的平台或代码库的约束,否则 HTTP 调用应该始终异步完成,并且 SDK 在这种情况下完全支持它。只需使用ExistsAsync() 而不是Exists()

                bool exists = await client.GetContainerReference(containerName)
                    .GetBlockBlobReference(key)
                    .ExistsAsync();
                

                【讨论】:

                • 你是对的,旧的 .Exists() 不是最好的选择。但是,虽然旧 API 是同步的,但使用 await 会导致 ExistsAsync 也是同步的。所以,我同意 HTTP 调用应该通常是异步的。但这段代码不是那样的。不过,为新 API +1!
                • 谢谢,但我完全不同意。 Exists() 是同步的,因为它阻塞一个线程直到它完成。 await ExistsAscyn() 是异步的,因为它不是。两者都遵循相同的逻辑流程,下一行代码在前一行代码完成之前不会开始,但ExistsAsync 的非阻塞特性使其异步。
                • 而且...我学到了一些新东西! :) softwareengineering.stackexchange.com/a/183583/38547
                【解决方案12】:

                借助 Azure Blob 存储库 v12,您可以使用 BlobBaseClient.Exists()/BlobBaseClient.ExistsAsync()

                回答了另一个类似的问题:https://stackoverflow.com/a/63293998/4865541

                【讨论】:

                  【解决方案13】:

                  Java 版本相同(使用新的 v12 SDK)

                  这使用共享密钥凭据授权(帐户访问密钥)

                  public void downloadBlobIfExists(String accountName, String accountKey, String containerName, String blobName) {
                      // create a storage client using creds
                      StorageSharedKeyCredential credential = new StorageSharedKeyCredential(accountName, accountKey);
                      String endpoint = String.format(Locale.ROOT, "https://%s.blob.core.windows.net", accountName);
                      BlobServiceClient storageClient = new BlobServiceClientBuilder().credential(credential).endpoint(endpoint).buildClient();
                  
                      BlobContainerClient container = storageClient.getBlobContainerClient(containerName);
                      BlobClient blob = container.getBlobClient(blobName);
                      if (blob.exists()) {
                          // download blob
                      } else {
                          // do something else
                      }
                  }
                  

                  【讨论】:

                  • 这只测试容器是否存在
                  • @Capuchin 感谢您指出这一点。我似乎粘贴了我对一个不正确问题的答案。我已经更新了答案。请看一看。
                  猜你喜欢
                  • 2013-07-05
                  • 1970-01-01
                  • 1970-01-01
                  • 2011-10-14
                  • 2020-06-04
                  • 2017-11-02
                  • 2021-05-16
                  • 2017-11-07
                  • 1970-01-01
                  相关资源
                  最近更新 更多