Azure StorageにBLOBが存在するかどうかの確認


131

私は非常に簡単な質問を持っています(私は願っています!)-特定のコンテナに(定義した名前の)blobが存在するかどうかを確認したいだけです。存在する場合はダウンロードし、存在しない場合は別の方法でダウンロードします。

インターチューブを検索したところ、DoesExistなどの関数があったようですが、Azure APIの多くと同様に、これは存在しないように見えます(ある場合は、非常に巧妙に偽装された名前)。


みんな、ありがとう。私はStorageClientを使用している(そして、すべてのAzure Storageアクセスをそのライブラリを介して保持したい)ので、smarxが提案するFetchAttributes-and-check-for-exceptionsメソッドを使用しました。ビジネスロジックの通常の部分として例外がスローされるのが好きではないため、少し気分が悪くなりますが、将来のStorageClientバージョンで修正できると幸いです:)
John

回答:


202

新しいAPIには.Exists()関数呼び出しがあります。GetBlockBlobReferenceサーバーへの呼び出しを実行しないを使用していることを確認してください。それは機能を次のように簡単にします:

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

6
.... pythonバージョンはありますか?
anpatel 14

2
blobが存在することを確認するために何が請求されますか?このdefoは、blobをダウンロードするよりも良い方法のようです。
DermFrench

10
@ anpatel、pythonバージョン:len(blob_service.list_blobs(container_name, file_name)) > 0
RaSi

3
nugetパッケージをインストールする必要がある答えを更新できます
batmaci

9
注:Microsoft.WindowsAzure.Storageバージョン8.1.4.0(.Net Framework v4.6.2)以降、Exists()メソッドは存在しません。ExistsAsync()は、.NetCoreプロジェクトにインストールされるバージョンです
Adam Hardy

49

注:この回答は現在古くなっています。存在を確認する簡単な方法については、リチャードの回答を参照してください

いいえ、単純なものを見逃していません...新しいStorageClientライブラリでこのメソッドを適切に非表示にしました。:)

私はあなたの質問に答えるためにブログ投稿を書きました: http //blog.smarx.com/posts/testing-existence-of-a-windows-azure-blob

短い答えは:BLOBに対してHEADリクエストを行うCloudBlob.FetchAttributes()を使用します。


1
FetchAttributes()は、ファイルがまだ完全にコミットされていない場合、つまりコミットされていないブロックのみで構成されている場合、(少なくとも開発ストレージで)実行に長い時間がかかります。
トムロビンソン

7
OPが意図するように、とにかくblobをフェッチする場合は、コンテンツをすぐにダウンロードしてみませんか?存在しない場合は、FetchAttributesと同じようにスローされます。最初にこのチェックを行うことは、追加のリクエストにすぎませんか、それとも何か不足していますか?
Marnix van Valen

Marnixは優れた点を示しています。とにかくそれをダウンロードするつもりなら、それをダウンロードしてみてください。
user94559 2010

@Marnix:そのようなものを呼び出してOpenReadも、空のStreamやそのようなものはスローまたは返されません。そこからダウンロードを開始したときにのみエラーが発生します。これをすべて1か所で処理する方がはるかに簡単です:)
porges

1
@Porges:クラウドアプリケーションの設計は、すべて「失敗のための設計」に関するものです。この状況を適切に処理する方法については多くの議論があります。しかし、一般的には-私もそれをダウンロードして、不足しているBlobエラーを処理します。それだけでなく、すべてのblobの存在を確認する場合は、ストレージトランザクションの数を増やして、請求額を増やします。例外/エラーを処理するための場所を1つ持つことができます。
astaykov

16

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

9

BLOBが公開されている場合は、もちろん、HTTP HEADリクエストを送信することができます-方法を知っている無数の言語/環境/プラットフォームから-応答を確認してください。

コアAzure APIは、RESTful XMLベースのHTTPインターフェイスです。StorageClientライブラリは、それらを囲む多くの可能なラッパーの1つです。Sriram KrishnanがPythonで行った別の方法を次に示します。

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

また、HTTPレベルで認証する方法も示します。

StorageClientライブラリのレンズではなく、HTTP / RESTのレンズを通してAzureを見る方が好きなので、私もC#で同様のことを行いました。しばらくの間、私はExistsBlobメソッドを実装することさえ気にしていませんでした。私のブロブはすべて公開されており、HTTP HEADを実行するのは簡単でした。


5

新しいWindows Azureストレージライブラリには、Exist()メソッドが既に含まれています。Microsoft.WindowsAzure.Storage.dllにあります。

NuGetパッケージとして利用可能
作成者:Microsoft
Id:WindowsAzure.Storage
バージョン:2.0.5.1

msdnも参照


2

例外メソッドを使用したくない場合は、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;
}

4
404がある場合、HttpWebRequest.GetResponseは例外をスローします。コードが例外を処理する必要性をどのように回避するのかわかりませんか?
Nitramk

フェアポイント。GetResponse()がその時点でスローするのはごみのようです!それがレスポンスなので404を返すと思います!!!
Mad Pierre

2

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


1

これが私のやり方です。それを必要とする人のために完全なコードを示しています。

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

1

ここでのほとんどの答えは技術的に正しいですが、ほとんどのコードサンプルは同期/ブロッキング呼び出しを行っています。非常に古いプラットフォームやコードベースに縛られていない限り、HTTP呼び出しは常に非同期で行う必要があり、SDKはこの場合完全にサポートします。のExistsAsync()代わりに使用してくださいExists()

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

正解です。古い.Exists()は最適なオプションではありません。ただし、古いAPIは同期ですが、await を使用すると、ExistsAsyncも同期します。したがって、HTTP呼び出しは通常は非同期でなければならないことに同意します。しかし、このコードはそうではありません。それでも、新しいAPIの+1です!
Richard

2
ありがとう、しかし私はこれ以上反対することができませんでした。Exists()完了するまでスレッドをブロックするという点で同期です。await ExistsAscyn()非同期ではありません。どちらも同じ論理フローに従いますが、次のコード行は前のコードが終了するまで開始されませんが、ノンブロッキングでExistsAsyncあるため非同期になります。
トッド・ムニエ

1
そして...私は何か新しいことを学びました!:) softwareengineering.stackexchange.com/a/183583/38547
リチャード

1

他のソリューションが気に入らない場合の別のソリューションを次に示します。

Azure.Storage.Blobs NuGetパッケージのバージョン12.4.1を使用しています。

コンテナー内のすべてのblobのリストであるAzure.Pageableオブジェクトを取得します。次に、BlobItemの名前が​​、LINQを利用するコンテナー内の各blobのNameプロパティと等しいかどうかを確認します。(もちろん、すべてが有効な場合)

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

うまくいけば、これは将来の誰かを助けるでしょう。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.