ตรวจสอบว่ามี Blob อยู่ใน Azure Storage หรือไม่


131

ฉันมีคำถามง่ายๆ (ฉันหวังว่า!) - ฉันแค่อยากรู้ว่ามีหยด (ที่มีชื่อที่ฉันกำหนดไว้) อยู่ในคอนเทนเนอร์หรือไม่ ฉันจะดาวน์โหลดถ้ามีอยู่และถ้าไม่มีฉันจะทำอย่างอื่น

ฉันได้ทำการค้นหาบน intertubes และเห็นได้ชัดว่าเคยมีฟังก์ชั่นที่เรียกว่า DoesExist หรือสิ่งที่คล้ายกัน ... แต่เช่นเดียวกับ Azure API จำนวนมากดูเหมือนว่าจะไม่มีอีกต่อไป (หรือถ้ามีก็มี ชื่อที่ปลอมตัวมาอย่างชาญฉลาด)


ขอบคุณทุกคน ขณะที่ฉันใช้ StorageClient (และต้องการให้การเข้าถึง Azure Storage ทั้งหมดของฉันผ่านไลบรารีนั้น) ฉันใช้วิธี FetchAttributes-and-check-for-exceptions ที่ smarx แนะนำ มัน 'รู้สึก' เล็กน้อยที่ฉันไม่ชอบมีข้อยกเว้นที่ถูกโยนทิ้งเป็นส่วนปกติของตรรกะทางธุรกิจของฉัน - แต่หวังว่าสิ่งนี้จะสามารถแก้ไขได้ในเวอร์ชัน StorageClient ในอนาคต :)
John

คำตอบ:


202

API ใหม่มีการเรียกใช้ฟังก์ชัน. Exists () ตรวจสอบให้แน่ใจว่าคุณใช้GetBlockBlobReferenceซึ่งไม่ได้ทำการโทรไปยังเซิร์ฟเวอร์ ทำให้ฟังก์ชั่นง่ายเหมือน:

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

6
มี .. a ... python version?
anpatel

2
สงสัยว่าคุณจะถูกเรียกเก็บเงินจากการตรวจสอบ blob หรือไม่? defo นี้ดูเหมือนจะเป็นวิธีที่ดีกว่าการพยายามดาวน์โหลดหยด
DermFrench

10
@anpatel เวอร์ชั่น python:len(blob_service.list_blobs(container_name, file_name)) > 0
RaSi

3
คุณสามารถอัปเดตคำตอบของคุณได้ว่าควรติดตั้ง
แพ็คเกจ nuget แบบใด

9
หมายเหตุ: สำหรับ Microsoft.WindowsAzure.Storage เวอร์ชัน 8.1.4.0 (.Net Framework v4.6.2) วิธีการ Exists () ไม่มีอยู่ในความโปรดปรานของ ExistsAsync () ซึ่งเป็นเวอร์ชันที่จะติดตั้งสำหรับโครงการ. NetCore
Adam Hardy

49

หมายเหตุ: คำตอบนี้ล้าสมัยแล้ว โปรดดูคำตอบของ Richard สำหรับวิธีง่ายๆในการตรวจสอบการมีอยู่จริง

ไม่คุณไม่พลาดอะไรง่ายๆ ... เราทำได้ดีในการซ่อนวิธีนี้ในไลบรารี StorageClient ใหม่ :)

ผมเพิ่งเขียนบล็อกโพสต์ที่จะตอบคำถามของคุณ: http://blog.smarx.com/posts/testing-existence-of-a-windows-azure-blob

คำตอบสั้น ๆ คือใช้ CloudBlob.FetchAttributes () ซึ่งส่งคำขอ HEAD กับหยด


1
FetchAttributes () ใช้เวลานานในการรัน (อย่างน้อยในพื้นที่จัดเก็บข้อมูลการพัฒนา) หากไฟล์ยังไม่ได้รับการยืนยันอย่างสมบูรณ์นั่นคือประกอบด้วยบล็อกที่ไม่ได้ผูกมัด
Tom Robinson

7
หากคุณกำลังจะดึงหยดเหมือนที่ OP ตั้งใจจะทำทำไมไม่ลองดาวน์โหลดเนื้อหาทันทีล่ะ ถ้าไม่มีก็จะโยนเหมือน FetchAttributes การตรวจสอบครั้งแรกเป็นเพียงคำขอเพิ่มเติมหรือฉันทำอะไรพลาด
Marnix van Valen

Marnix เป็นจุดที่ยอดเยี่ยม หากคุณกำลังจะดาวน์โหลดเพียงแค่ลองดาวน์โหลด
user94559

@Marnix: ถ้าคุณเรียกอะไรแบบOpenReadนั้นมันจะไม่โยนหรือส่งคืนสตรีมที่ว่างเปล่าหรืออะไรทำนองนั้น คุณจะได้รับข้อผิดพลาดเมื่อคุณเริ่มดาวน์โหลดจากมัน จัดการทั้งหมดนี้ได้ง่ายกว่ามากในที่เดียว :)
porges

1
@ Porges: การออกแบบแอปพลิเคชันระบบคลาวด์เป็นเรื่องของ "การออกแบบเพื่อความล้มเหลว" มีการพูดคุยมากมายว่าจะรับมือกับสถานการณ์นี้อย่างไร แต่โดยทั่วไป - ฉันจะไปดาวน์โหลดจากนั้นจัดการข้อผิดพลาด Blob ที่หายไป ไม่เพียงแค่นั้น แต่ถ้าฉันจะตรวจสอบการมีอยู่ทุกๆหยดฉันจะเพิ่มจำนวนธุรกรรมการจัดเก็บข้อมูลดังนั้นการเรียกเก็บเงินของฉัน คุณยังสามารถมีที่เดียวสำหรับจัดการข้อยกเว้น / ข้อผิดพลาด
astaykov

16

ดูเหมือนง่อยที่คุณต้องจับข้อยกเว้นเพื่อทดสอบว่ามีหยดอยู่

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

หากหยดเป็นแบบสาธารณะคุณสามารถทำได้เพียงแค่ส่งคำขอ HTTP HEAD จากภาษา / สภาพแวดล้อม / แพลตฟอร์มใด ๆ จาก zillions ที่รู้วิธีการทำเช่นนั้นและตรวจสอบการตอบสนอง

Azure API หลักคืออินเทอร์เฟซ HTTP ที่ใช้ XML RESTful ไลบรารี StorageClient เป็นหนึ่งในอุปกรณ์ห่อหุ้มที่เป็นไปได้มากมาย นี่คืออีกสิ่งหนึ่งที่ Sriram Krishnan ทำใน Python:

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

นอกจากนี้ยังแสดงวิธีการรับรองความถูกต้องในระดับ HTTP

ฉันได้ทำสิ่งที่คล้ายกันสำหรับตัวเองใน C # เพราะฉันชอบที่จะเห็น Azure ผ่านเลนส์ของ HTTP / REST มากกว่าผ่านเลนส์ของไลบรารี StorageClient ในขณะที่ฉันไม่ได้ใส่ใจที่จะใช้เมธอด ExistsBlob Blobs ทั้งหมดของฉันเป็นแบบสาธารณะและเป็นเรื่องเล็กน้อยที่จะทำ HTTP HEAD


5

Windows Azure Storage Library ใหม่มีเมธอด Exist () อยู่แล้ว อยู่ใน Microsoft.WindowsAzure.Storage.dll

พร้อมใช้งานเป็นแพ็คเกจ NuGet
สร้างโดย: Microsoft
Id: WindowsAzure
เวอร์ชันที่จัดเก็บ: 2.0.5.1

ดู msdn ด้วย


2

หากคุณไม่ชอบใช้วิธีการยกเว้นรุ่น c # พื้นฐานของสิ่งที่ Judell แนะนำอยู่ด้านล่าง ระวังว่าคุณควรจัดการกับคำตอบอื่น ๆ ด้วย

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 จะแสดงข้อยกเว้นหากมี 404 ดังนั้นฉันจึงไม่เห็นว่าโค้ดของคุณจะหลีกเลี่ยงความจำเป็นในการจัดการข้อยกเว้นได้อย่างไร
Nitramk

จุดยุติธรรม ดูเหมือนขยะสำหรับฉันที่ GetResponse () พ่น ณ จุดนั้น! ฉันคาดหวังว่ามันจะกลับมา 404 ตามที่ได้รับการตอบสนอง !!!
Mad Pierre

2

หากหยดของคุณเป็นแบบสาธารณะและคุณต้องการเพียงแค่ข้อมูลเมตา:

        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 ควรเสมอทำได้ asynchonously และ SDK สนับสนุนอย่างเต็มที่ในกรณีนี้ เพียงแค่ใช้ExistsAsync()แทนExists().

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

คุณถูกต้องแล้ว. Exists () เก่าไม่ใช่ตัวเลือกที่ดีที่สุด อย่างไรก็ตามในขณะที่ API เก่าเป็นแบบซิงโครนัสการใช้await ทำให้ ExistsAsync ซิงโครนัสด้วย ดังนั้นผมจะเห็นว่าสาย HTTP ควรมักจะไม่ตรงกัน แต่รหัสนี้ไม่เป็นเช่นนั้น ยังคง +1 สำหรับ API ใหม่!
Richard

2
ขอบคุณ แต่ฉันไม่เห็นด้วยมากกว่านี้ Exists()เป็นซิงโครนัสที่บล็อกเธรดจนกว่าจะเสร็จสมบูรณ์ await ExistsAscyn()เป็นแบบอะซิงโครนัสซึ่งไม่ได้ ทั้งสองทำตามลำดับตรรกะเดียวกันโดยที่บรรทัดถัดไปของโค้ดจะไม่เริ่มต้นจนกว่าโค้ดก่อนหน้าจะเสร็จสิ้น แต่ลักษณะการไม่ปิดกั้นExistsAsyncทำให้เป็นแบบอะซิงโครนัส
Todd Menier

1
และ ... ฉันได้เรียนรู้สิ่งใหม่ ๆ ! :) softwareengineering.stackexchange.com/a/183583/38547
Richard

1

นี่เป็นวิธีอื่นหากคุณไม่ชอบวิธีแก้ปัญหาอื่น ๆ :

ฉันใช้ Azure.Storage.Blobs NuGet Package เวอร์ชัน 12.4.1

ฉันได้รับAzureวัตถุที่เพจได้ซึ่งเป็นรายการของ blobs ทั้งหมดในคอนเทนเนอร์ จากนั้นตรวจสอบว่าชื่อของBlobItemเท่ากับคุณสมบัติ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;
        }
    }
}

หวังว่าสิ่งนี้จะช่วยใครบางคนในอนาคต

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.