Azure Storage에 Blob이 있는지 확인


131

매우 간단한 질문이 있습니다 (희망합니다!)-특정 컨테이너에 blob (이름이 정의 된)이 있는지 확인하고 싶습니다. 존재하는 경우 다운로드하고 그렇지 않은 경우 다른 작업을 수행합니다.

나는 intertubes에서 약간의 검색을 수행했으며 DoesExist 또는 이와 유사한 기능이 있었을 것입니다 ...하지만 많은 Azure API와 마찬가지로 더 이상 존재하지 않는 것 같습니다. 매우 영리하게 위장한 이름).


모두 감사합니다. StorageClient를 사용하면서 (그리고 해당 라이브러리를 통과하는 모든 Azure 저장소 액세스를 유지하려는 경우) smarx가 제안한 FetchAttributes-and-ex-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
.... 파이썬 버전이 있습니까?
anpatel

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 () 메서드는 .NetCore 프로젝트에 설치할 버전 인 ExistsAsync ()를 선호하지 않습니다
Adam Hardy

49

참고 :이 답변은 최신 정보가 아닙니다. 존재 여부를 쉽게 확인할 수있는 Richard의 답변을 참조하십시오

아니요, 간단한 것이 빠진 것이 아닙니다. 새로운 StorageClient 라이브러리에서이 메소드를 숨기는 작업이 훌륭했습니다. :)

방금 귀하의 질문에 대답하기 위해 블로그 게시물을 작성했습니다 : http://blog.smarx.com/posts/testing-existence-of-a-windows-azure-blob .

짧은 답변은 CloudBlob.FetchAttributes ()를 사용하는 것입니다. CloudBlob.FetchAttributes ()는 BLOB에 대한 HEAD 요청을 수행합니다.


1
파일이 아직 완전히 커밋되지 않은 경우, 즉 커밋되지 않은 블록으로 만 구성된 경우 FetchAttributes ()는 개발 저장소에서 실행하는 데 시간이 오래 걸립니다.
Tom Robinson

7
OP가 의도 한대로 blob을 가져 오려면 바로 콘텐츠를 다운로드하여 다운로드 해보십시오. 존재하지 않으면 FetchAttributes와 같이 throw됩니다. 이 확인을 먼저하는 것은 추가 요청 일 뿐입니 까, 아니면 뭔가 빠졌습니까?
Marnix van Valen

Marnix는 훌륭한 지적을합니다. 어쨌든 다운로드하려면 다운로드하십시오.
user94559

@Marnix : 전화를 걸면 OpenRead빈 스트림이나 그와 비슷한 것을 던지거나 반환하지 않습니다. 다운로드를 시작할 때만 오류가 발생합니다. 이 모든 것을 한곳에서 처리하는 것이 훨씬 쉽습니다 :)
porges

1
@Porges : 클라우드 애플리케이션 설계는 "실패를위한 설계"에 관한 것입니다. 이 상황을 올바르게 처리하는 방법에 대한 많은 토론이 있습니다. 그러나 일반적으로-그냥 가서 다운로드 한 다음 누락 된 Blob 오류를 처리합니다. 뿐만 아니라 모든 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

Blob이 공개적이라면 물론 HTTP HEAD 요청 (어떻게 하는지를 알고있는 수많은 언어 / 환경 / 플랫폼에서)을 보내 응답을 확인할 수 있습니다.

핵심 Azure API는 RESTful XML 기반 HTTP 인터페이스입니다. StorageClient 라이브러리는 가능한 많은 랩퍼 중 하나입니다. Sriram Krishnan이 Python에서 한 또 다른 기능은 다음과 같습니다.

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

또한 HTTP 레벨에서 인증하는 방법을 보여줍니다.

C #에서도 비슷한 일을했습니다. StorageClient 라이브러리의 렌즈가 아닌 HTTP / REST의 렌즈를 통해 Azure를 보는 것을 선호하기 때문입니다. 꽤 오랫동안 ExistsBlob 메서드를 구현하지 않아도되었습니다. 내 모든 blob은 공개되었으며 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인해 비동기식입니다.
Todd Menier

1
그리고 ... 나는 새로운 것을 배웠습니다! :) softwareengineering.stackexchange.com/a/183583/38547
Richard

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.