检查 Azure 存储中是否存在一个 blob

我有一个非常简单的问题(我希望!)我只是想知道一个 blob (带有我定义的名称)是否存在于一个特定的容器中。如果它确实存在,我会下载它,如果它不存在,那么我会做别的事情。

我在网络上做了一些搜索,显然曾经有一个叫 DoesExist 的函数或者类似的东西... ... 但是和很多 Azure API 一样,这个函数似乎不再存在了(或者如果存在的话,它有一个非常巧妙的名字)。

105471 次浏览

注意: 这个答案现在已经过时了。请参阅理查德的答案,它提供了一个简单的方法来检查是否存在

不,您不会错过一些简单的东西... ... 我们在新的 StorageClient 库中很好地隐藏了这个方法。:)

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

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

当然,如果 blob 是公共的,那么只需发送一个 HTTP HEAD 请求——来自知道如何做到这一点的无数语言/环境/平台中的任何一个——并检查响应。

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

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

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

我自己在 C # 中也做过类似的事情,因为我更喜欢通过 HTTP/REST 的透镜来看 Azure,而不是通过 StorageClient 库的透镜来看 Azure。有很长一段时间,我甚至懒得去实现赖以存在的 Blob 方法。我的所有 blob 都是公共的,而且做 HTTPHEAD 非常简单。

你需要捕获一个异常来测试这个 blob 是否存在,这看起来很无聊。

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

如果您不喜欢使用异常方法,那么下面是 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;
}

新的 WindowsAzure 存储库已经包含了 Exist ()方法。 它在微软,WindowsAzure,Storage.dll。

有 NuGet 软件包
创建者: Microsoft
ID: WindowsAzure. 存储
版本: 2.0.5.1

也见 msdn

新的 API 具有。存在()函数调用。只需确保使用 GetBlockBlobReference,它不执行对服务器的调用。它使得功能简单如下:

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

使用更新后的 SDK,一旦有了 CloudBlobReference,就可以对引用调用 Exists ()。

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

我就是这么做的,为需要的人显示完整代码。

        // 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.
}

尽管这里的大多数答案在技术上是正确的,但是大多数代码示例都进行了同步/阻塞调用。除非您受到一个非常老的平台或代码库的约束,否则应该异步执行 HTTP 调用 一直都是,在这种情况下 SDK 完全支持它。只要使用 ExistsAsync()而不是 Exists()

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

如果你的 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

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

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

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

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;
}
}
}

希望这能帮到将来的某个人。

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

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

同样的 Java 版本(使用新的 v12SDK)

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

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
}
}