Как получить ссылки на объекты BlockBlob из CloudBlobDirectory.ListBlobs?

Я использую клиентские библиотеки Microsoft Azure.NET для взаимодействия с облачным хранилищем Azure. Мне нужно иметь доступ к дополнительной информации о каждом блоке в его коллекции метаданных. В настоящее время я использую метод CloudBlobDirectory.ListBlobs(), чтобы получить список blob в определенном каталоге структуры каталога, которую я разработал в именах blob. Метод ListBlobs() возвращает список объектов IListBlobItem. У них есть только несколько свойств: Url и ссылки на родительский каталог и родительский контейнер. Мне нужно добраться до метаданных фактических объектов blob.

Я предполагал, что был бы способ либо передать IListBlobItem в объект BlockBlob, либо использовать IListBlockItem, чтобы получить ссылку на BlockBlob, но не может найти способ сделать это.

Мой вопрос: есть ли способ получить объект BlockBlob из этого метода или мне нужно использовать другой способ получения фактических объектов BlockBlob? Если отличается, то можете ли вы предложить способ достижения этого, а также возможность фильтровать по схеме "каталог"?

Ответ 1

ОК... Я нашел способ сделать это, и, хотя он кажется немного неуклюжим и косвенным, он достигает главного, что, как я думал, должно быть выполнимым, а именно, чтобы заставить IListBlobItem напрямую облачиться в объект CloudBlockBlob.

То, что я делаю, это получить список из метода ListBlobs() объекта Directory Object, а затем перебрать каждый элемент в списке и передать объект в объект CloudBlockBlob, а затем вызвать метод FetchAttributes() для извлечения свойств (в том числе метаданные). Затем добавьте новый объект "информация" в новый список объектов информации. Вот код, который я использую:

CloudBlobDirectory dir = container.GetDirectoryReference(dirPath);

var blobs = dir.ListBlobs(true);

foreach (IListBlobItem item in blobs)
{
    CloudBlockBlob blob = (CloudBlockBlob)item;
    blob.FetchAttributes();
    files.Add(new ImageInfo
    {
        FileUrl = item.Uri.ToString(),
        FileName = item.Uri.PathAndQuery.Replace(restaurantId.ToString().PadLeft(3, '0') + "/", ""),
        ImageName = blob.Metadata["Name"]
    });
}

Вся концепция "Blob" кажется излишне сложной и, похоже, не достигла того, что я считал бы одной из основных особенностей оболочки Blob. То есть, способ расширить возможности поиска, разрешив запрос по имени, каталогу, контейнеру и метаданным. Я бы подумал, что вы можете построить запрос linq, который будет выглядеть примерно так: "верните список всех блоков в контейнере" images ", которые находятся в пути к каталогу" natural/landscapes/ ", в котором есть ключ метаданных ' категория" со значением "закат". Кажется, что нет способа сделать это, и это кажется упущенной возможностью для меня. О, хорошо.

Если я ошибаюсь и ухожу отсюда, пожалуйста, дайте мне знать.

Ответ 2

Этот подход был разработан для Java, но я надеюсь, что его можно каким-то образом изменить, чтобы он соответствовал любому другому поддерживаемому языку программирования. Несмотря на то, что функциональность, о которой вы просите, еще не была явно разработана, я думаю, что нашел другой (надеюсь, менее cluncky) способ доступа к данным CloudBlockBlob из элемента ListBlobItem.

Следующий код может использоваться для удаления, например, каждого блоба внутри конкретного каталога.

String blobUri;
CloudBlobClient blobClient = /* Obtain your blob client */

try{
     CloudBlobContainer container = /* Obtain your blob container */

     for (ListBlobItem blobItem : container.listBlobs(blobPrefix)) {

          if (blobItem instanceof CloudBlob) {
                blob = (CloudBlob) blobItem;
                if (blob.exists()){
                    System.out.println("Deleting blob " + blob.getName());
                    blob.delete();
                }
          }
     }
}catch (URISyntaxException | StorageException ex){
        Logger.getLogger(BlobOperations.class.getName()).log(Level.SEVERE, null, ex);
}

Ответ 3

Предыдущие ответы хороши. Я просто хотел указать на две вещи:

1) . В настоящее время рекомендуется программирование ASYNC, которое также поддерживается Azure SDK. Поэтому попробуйте использовать это:

CloudBlobDirectory dir = container.GetDirectoryReference(dirPath);
var blobs = dir.ListBlobs(true);

foreach (IListBlobItem item in blobs)
{
    CloudBlockBlob blob = (CloudBlockBlob)item;
    await blob.FetchAttributesAsync(); //Use async calls...
}

2) Извлечение метаданных в отдельном вызове неэффективно. Код выполняет 2 HTTP-запроса на каждый объект BLOB-объекта. Метод ListBlobs() поддерживает получение метаданных с помощью одного вызова, устанавливая параметр BlobListingDetails:

CloudBlobDirectory dir = container.GetDirectoryReference(dirPath);
var blobs = dir.ListBlobs(useFlatBlobListing: true, blobListingDetails: BlobListingDetails.Metadata);

Я рекомендую использовать второй код, это возможно. Так как это самый эффективный способ получения метаданных.