Azure Storage'da bir blob olup olmadığını kontrol etme


131

Çok basit bir sorum var (umarım!) - Sadece belirli bir kapta bir blobun (tanımladığım bir adla) olup olmadığını öğrenmek istiyorum. Varsa indireceğim, yoksa başka bir şey yapacağım.

İntertüplerde biraz arama yaptım ve görünüşe göre DoesExist adında bir işlev veya benzer bir şey vardı ... ama Azure API'lerinin çoğunda olduğu gibi, bu artık orada görünmüyor (veya eğer varsa, bir çok zekice gizlenmiş isim).


Herkese teşekkürler. StorageClient'i kullandığım için (ve tüm Azure Depolama erişimimin bu kitaplık üzerinden devam etmesini tercih ettiğim için) smarx'ın önerdiği FetchAttributes-and-check-for-exceptions yöntemini kullandım. İş mantığımın normal bir parçası olarak atılan istisnalardan hoşlanmadığım için biraz 'kötü' hissettiriyor - ancak umarım bu gelecekteki bir StorageClient sürümünde düzeltilebilir :)
John

Yanıtlar:


202

Yeni API, .Exists () işlev çağrısına sahiptir. Sadece GetBlockBlobReference, sunucuya çağrı yapmayan, kullandığınızdan emin olun . İşlevi şu kadar kolay hale getirir:

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

6
Python versiyonu var mı?
anpatel

2
Blobun var olup olmadığını kontrol ettiğiniz için ne kadar ücret alacağınızı merak ediyor musunuz? Bu defo, blob'u indirmeye çalışmaktan daha iyi bir yol gibi görünüyor.
DermFrench

10
@anpatel, python sürümü:len(blob_service.list_blobs(container_name, file_name)) > 0
RaSi

3
cevabınızı hangi nuget paketinin yüklenmesi gerektiğini güncelleyebilirsiniz
batmaci

9
NOT: Microsoft.WindowsAzure.Storage sürüm 8.1.4.0 (.Net Framework v4.6.2) itibarıyla Exists () yöntemi, .NetCore projeleri için yüklenecek sürüm olan ExistsAsync () lehine mevcut değildir
Adam Hardy

49

Not: Bu yanıt artık güncel değil. Varlığı kontrol etmenin kolay bir yolu için lütfen Richard'ın cevabına bakın

Hayır, basit bir şeyi kaçırmıyorsunuz ... Bu yöntemi yeni StorageClient kitaplığında saklayarak iyi bir iş çıkardık. :)

Sorunuzu yanıtlamak için bir blog yazısı yazdım: http://blog.smarx.com/posts/testing-existence-of-a-windows-azure-blob .

Kısa cevap şudur: blob'a karşı bir HEAD isteği yapan CloudBlob.FetchAttributes () kullanın.


1
FetchAttributes (), eğer dosya henüz tam olarak kaydedilmediyse (en azından geliştirme depolamasında), yani sadece taahhüt edilmemiş bloklardan oluşuyorsa uzun zaman alır.
Tom Robinson

7
Blobu yine de OP'nin yapmayı planladığı gibi getirecekseniz, neden içeriği hemen indirmeyi denemiyorsunuz? Orada değilse, aynı FetchAttributes gibi atar. Önce bu kontrolü yapmak sadece fazladan bir istek mi yoksa bir şeyi mi kaçırıyorum?
Marnix van Valen

Marnix mükemmel bir noktaya işaret ediyor. Yine de indirecekseniz, indirmeyi deneyin.
user94559

@Marnix: Böyle bir şeyi ararsanız OpenReadboş bir Akış veya benzeri bir şey atmaz veya geri döndürmez. Yalnızca indirmeye başladığınızda hata alırsınız. Bunların hepsini tek bir yerde halletmek çok daha kolay :)
porges

1
@Porges: Bulut uygulaması tasarlamak tamamen "başarısızlık için tasarım" ile ilgilidir. Bu durumun nasıl düzgün bir şekilde ele alınacağı konusunda birçok tartışma var. Ama genel olarak - ben de gidip indiriyor, sonra eksik Blob hatalarını hallediyordum. Sadece bu da değil, her blobun var olup olmadığını kontrol edeceksem, depolama işlemlerinin sayısını, dolayısıyla faturamı arttırıyorum. İstisnaları / Hataları ele almak için hala tek bir yeriniz olabilir.
astaykov

16

Blobun var olduğunu test etmek için bir istisna yakalamaya ihtiyacınız var gibi görünüyor.

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 herkese açıksa, tabii ki, bunu nasıl yapacağını bilen zilyonlarca dil / ortam / platformdan herhangi birinden bir HTTP HEAD isteği gönderebilir ve yanıtı kontrol edebilirsiniz.

Çekirdek Azure API'leri, RESTful XML tabanlı HTTP arabirimleridir. StorageClient kitaplığı, etraflarındaki birçok olası sarmalayıcıdan biridir. İşte Sriram Krishnan'ın Python'da yaptığı bir başka şey:

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

Ayrıca HTTP düzeyinde nasıl kimlik doğrulaması yapılacağını da gösterir.

Ben de C # 'da kendim için benzer bir şey yaptım çünkü Azure'u StorageClient kitaplığının lensi yerine HTTP / REST lensinden görmeyi tercih ediyorum. Bir süredir ExistsBlob yöntemini uygulamaya zahmet etmedim bile. Tüm bloblarım halka açıktı ve HTTP HEAD yapmak önemsizdi.


5

Yeni Windows Azure Depolama Kitaplığı zaten Exist () yöntemini içeriyor. Microsoft.WindowsAzure.Storage.dll dosyasındadır.

NuGet Paketi olarak kullanılabilir
Oluşturan: Microsoft
Id: WindowsAzure.Storage
Sürüm: 2.0.5.1

Ayrıca msdn'ye bakın


2

İstisna yöntemini kullanmaktan hoşlanmıyorsanız, judell'in önerdiği temel c # sürümü aşağıdadır. Diğer olası yanıtları da gerçekten ele almanız gerektiğine dikkat edin.

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
HttpWebRequest.GetResponse, bir 404 varsa bir istisna atar. Yani, kodunuzun istisnaları işleme ihtiyacını nasıl atlatacağını anlamıyorum?
Nitramk

Doğru tespit. Bana GetResponse () 'nin o noktada fırlattığı çöp gibi görünüyor! 404'ü geri getirmesini bekliyorum, çünkü cevap bu !!!
Mad Pierre

2

Blobunuz herkese açıksa ve yalnızca meta veriye ihtiyacınız varsa:

        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

Ben böyle yapıyorum. İhtiyaç duyanlar için tam kod gösteriliyor.

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

Buradaki yanıtların çoğu teknik olarak doğru olsa da, çoğu kod örneği eşzamanlı / engelleyici çağrılar yapıyor. Çok eski bir platforma veya kod tabanına bağlı olmadığınız sürece, HTTP çağrıları her zaman eşzamansız olarak yapılmalıdır ve bu durumda SDK bunu tam olarak destekler. Bunun ExistsAsync()yerine kullanın Exists().

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

Doğru söylüyorsun, eski .Exists () en iyi seçenek değil. Ancak, eski API eşzamanlıyken, await kullanımı ExistsAsync'in de eşzamanlı olmasına neden olur. Bu nedenle, HTTP çağrılarının genellikle eşzamansız olması gerektiğini kabul ediyorum . Ama bu kod o değil. Yine de, yeni API için +1!
Richard

2
Teşekkürler, ama daha fazla katılmıyorum. Exists()eşzamanlıdır, çünkü tamamlanana kadar bir iş parçacığını engeller. await ExistsAscyn()asenkron olduğundan dolayı değildir. Her ikisi de aynı mantıksal akışı izler, çünkü bir sonraki kod satırı bir önceki bitene kadar başlamaz, ancak ExistsAsyncbu, onu eşzamansız kılan engelsiz doğasıdır .
Todd Menier

1
Ve ... yeni bir şey öğrendim! :) softwareengineering.stackexchange.com/a/183583/38547
Richard

1

Diğer çözümleri beğenmezseniz işte farklı bir çözüm:

Azure.Storage.Blobs NuGet Paketinin 12.4.1 sürümünü kullanıyorum.

Bir konteynerdeki tüm blobların listesi olan bir Azure.Pageable nesnesi alıyorum . Daha sonra BlobItem adının LINQ kullanan konteyner içindeki her blobun Name özelliğine eşit olup olmadığını kontrol ediyorum . (Her şey geçerliyse elbette)

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

Umarım bu gelecekte birine yardımcı olur.


Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.