Kiểm tra nếu một blob tồn tại trong Azure Storage


131

Tôi đã có một câu hỏi rất đơn giản (tôi hy vọng!) - Tôi chỉ muốn tìm hiểu xem một blob (với tên tôi đã xác định) có tồn tại trong một container cụ thể không. Tôi sẽ tải xuống nếu nó tồn tại và nếu không thì tôi sẽ làm một cái gì đó khác.

Tôi đã thực hiện một số tìm kiếm trên các intertubes và dường như đã từng có một hàm gọi là DoesExist hoặc một cái gì đó tương tự ... nhưng cũng như rất nhiều API Azure, điều này dường như không còn nữa (hoặc nếu nó có, có tên rất ngụy trang khéo léo).


Cảm ơn mọi người. Vì tôi đang sử dụng StorageClient (và muốn giữ tất cả quyền truy cập Azure Storage của mình đi qua thư viện đó), tôi đã sử dụng phương pháp FetchAttribut-and-check-for-exceptions mà smarx đề xuất. Nó hơi 'cảm thấy' một chút, ở chỗ tôi không thích có ngoại lệ bị ném như một phần bình thường trong logic kinh doanh của mình - nhưng hy vọng điều này có thể được khắc phục trong phiên bản StorageClient trong tương lai :)
John

Câu trả lời:


202

API mới có lệnh gọi hàm .Exists (). Chỉ cần đảm bảo rằng bạn sử dụng GetBlockBlobReference, không thực hiện cuộc gọi đến máy chủ. Nó làm cho chức năng dễ dàng như:

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

6
Có .. một ... phiên bản trăn?
anpatel

2
Tự hỏi những gì bạn bị tính phí để kiểm tra blob tồn tại? Defo này có vẻ như là một cách tốt hơn để cố gắng tải về blob.
DermFbler

10
@anpatel, phiên bản trăn:len(blob_service.list_blobs(container_name, file_name)) > 0
RaSi

3
bạn có thể cập nhật câu trả lời của mình với gói
nuget nào

9
LƯU Ý: Kể từ Microsoft.WindowsAzure.Storage phiên bản 8.1.4.0 (.Net Framework v4.6.2), phương thức Exists () không tồn tại có lợi cho ExistsAsync () Đây là phiên bản sẽ cài đặt cho các dự án .NetCore
Adam Hardy

49

Lưu ý: Câu trả lời này đã hết hạn ngay bây giờ. Vui lòng xem câu trả lời của Richard để biết cách dễ dàng kiểm tra sự tồn tại

Không, bạn không thiếu thứ gì đơn giản ... chúng tôi đã làm rất tốt khi ẩn phương thức này trong thư viện StorageClient mới. :)

Tôi vừa viết một bài đăng trên blog để trả lời câu hỏi của bạn: http://blog.smarx.com/posts/testing-existence-of-a-windows-azure-blob .

Câu trả lời ngắn gọn là: sử dụng CloudBlob.FetchAttribut (), yêu cầu CHÍNH đối với blob.


1
FetchAttribut () mất nhiều thời gian để chạy (ít nhất là trong bộ lưu trữ phát triển) nếu tệp chưa được cam kết đầy đủ, tức là chỉ bao gồm các khối không được cam kết.
Tom Robinson

7
Nếu bạn định tải blob bằng mọi cách như OP dự định sẽ làm, tại sao không thử và tải xuống nội dung ngay lập tức? Nếu nó không ở đó, nó sẽ ném giống như FetchAttribut. Thực hiện kiểm tra này trước tiên chỉ là một yêu cầu bổ sung, hoặc tôi đang thiếu một cái gì đó?
Marnix van Valen

Marnix làm cho một điểm tuyệt vời. Nếu bạn định tải xuống bằng mọi giá, hãy thử tải xuống.
dùng94559

@Marnix: Nếu bạn gọi một cái gì đó giống như OpenReadnó sẽ không ném hoặc trả lại một luồng trống hoặc bất cứ thứ gì tương tự. Bạn sẽ chỉ gặp lỗi khi bạn bắt đầu tải xuống từ nó. Thật dễ dàng hơn nhiều để xử lý tất cả những thứ này ở một nơi :)
porges 8/12/2016

1
@Porges: thiết kế ứng dụng đám mây là tất cả về "thiết kế cho sự thất bại". Có rất nhiều cuộc thảo luận làm thế nào để xử lý đúng tình huống này. Nhưng nói chung - tôi cũng sẽ chỉ đi và tải xuống, sau đó xử lý các lỗi Blob bị thiếu. Không chỉ vậy, nhưng nếu tôi sẽ kiểm tra sự tồn tại thì mỗi blob tôi sẽ tăng số lượng giao dịch lưu trữ, do đó, hóa đơn của tôi. Bạn vẫn có thể có một nơi để xử lý Ngoại lệ / Lỗi.
astaykov

16

Có vẻ khập khiễng rằng bạn cần phải bắt một ngoại lệ để kiểm tra xem blob tồn tại.

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

Tất nhiên, nếu blob là công khai, bạn có thể gửi yêu cầu HTTP Head - từ bất kỳ ngôn ngữ / môi trường / nền tảng nào biết cách thực hiện điều đó - và kiểm tra phản hồi.

Các API Azure cốt lõi là các giao diện HTTP dựa trên XML RESTful. Thư viện StorageClient là một trong nhiều trình bao bọc có thể có xung quanh chúng. Đây là một cái khác mà Sriram Krishnan đã làm trong Python:

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

Nó cũng cho thấy cách xác thực ở cấp HTTP.

Tôi đã làm một điều tương tự cho bản thân mình trong C #, vì tôi thích thấy Azure thông qua lăng kính HTTP / REST hơn là qua ống kính của thư viện StorageClient. Trong một thời gian dài, tôi thậm chí không bận tâm đến việc thực hiện phương thức ExistsBlob. Tất cả các đốm màu của tôi là công khai và thật đơn giản để thực hiện HTTP Head.


5

Thư viện lưu trữ Windows Azure mới đã chứa phương thức Exist (). Nó có tên trong Microsoft.WindowsAzure.Storage.dll.

Có sẵn dưới dạng Gói NuGet
Được tạo bởi: Microsoft
Id: WindowsAzure.Storage
Phiên bản: 2.0.5.1

Xem thêm


2

Nếu bạn không thích sử dụng phương pháp ngoại lệ thì phiên bản c # cơ bản của những gì Judell gợi ý là bên dưới. Hãy coi chừng rằng bạn thực sự phải xử lý các phản ứng khác có thể quá.

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 đưa ra một ngoại lệ nếu có 404. Vì vậy, tôi không thấy mã của bạn sẽ tránh được nhu cầu xử lý các trường hợp ngoại lệ như thế nào?
Nitramk

Điểm công bằng. Có vẻ như rác rưởi với tôi rằng GetResponse () ném vào thời điểm đó! Tôi hy vọng nó sẽ trả về 404 vì đó là phản hồi !!!
Mad Pierre

2

Nếu blob của bạn là công khai và bạn chỉ cần siêu dữ liệu:

        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

Đây là cách tôi làm. Hiển thị mã đầy đủ cho những người cần nó.

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

Mặc dù hầu hết các câu trả lời ở đây đều đúng về mặt kỹ thuật, hầu hết các mẫu mã đều thực hiện các cuộc gọi đồng bộ / chặn. Trừ khi bạn bị ràng buộc bởi một nền tảng hoặc cơ sở mã rất cũ, các cuộc gọi HTTP phải luôn luôn được thực hiện một cách bất thường và SDK hỗ trợ đầy đủ cho nó trong trường hợp này. Chỉ cần sử dụng ExistsAsync()thay vì Exists().

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

Bạn đã đúng, .Exists () cũ không phải là lựa chọn tốt nhất. Tuy nhiên, trong khi API cũ là đồng bộ, việc sử dụng chờ đợi khiến ExistsAsync cũng đồng bộ. Vì vậy, tôi đồng ý rằng các cuộc gọi HTTP thường không đồng bộ. Nhưng mã này không phải vậy. Tuy nhiên, +1 cho API mới!
Richard

2
Cảm ơn, nhưng tôi không thể không đồng ý nhiều hơn. Exists()là đồng bộ ở chỗ nó chặn một luồng cho đến khi hoàn thành. await ExistsAscyn()không đồng bộ ở chỗ nó không. Cả hai đều theo cùng một luồng logic trong đó dòng mã tiếp theo không bắt đầu cho đến khi dòng trước đó được thực hiện, nhưng chính bản chất không chặn của ExistsAsyncnó làm cho nó không đồng bộ.
Todd Menier

1
Và ... tôi đã học được điều gì đó mới! :) phần
Richard

1

Đây là một giải pháp khác nếu bạn không thích các giải pháp khác:

Tôi đang sử dụng phiên bản 12.4.1 của Gói NuGet Azure.Storage.Blobs.

Tôi nhận được một đối tượng Azure.Pagizable là danh sách tất cả các đốm màu trong một thùng chứa. Sau đó tôi kiểm tra xem tên của BlobItem có bằng với thuộc tính Name của mỗi blob bên trong container sử dụng LINQ không . (Nếu tất cả mọi thứ là hợp lệ, tất nhiên)

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

Hy vọng điều này sẽ giúp ai đó trong tương lai.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.