20

我正在使用 Microsoft Azure .NET 客户端库与 Azure 云存储进行交互。我需要能够访问有关其元数据集合中每个 blob 的附加信息。我目前正在使用 CloudBlobDirectory.ListBlobs() 方法来获取我在 blob 名称中设计的目录结构的特定目录中的 blob 列表。ListBlobs() 方法返回 IListBlobItem 对象的列表。它们只有几个属性:Url 以及对父目录和父容器的引用。我需要获取实际 blob 对象的元数据。

我设想有一种方法可以将 IListBlobItem 转换为 BlockBlob 对象,或者使用 IListBlockItem 来获取对 BlockBlob 的引用,但似乎找不到这样做的方法。

我的问题是:有没有办法从这个方法中获取 BlockBlob 对象,还是我必须使用不同的方式来获取实际的 BlockBlob 对象?如果不同,那么您能否提出一种实现此目的的方法,同时还能够通过“目录”方案进行过滤?

4

3 回答 3

24

好的...我找到了一种方法来做到这一点,虽然它看起来有点笨拙和间接,但它确实实现了我认为应该可行的主要事情,即将 IListBlobItem 直接转换为 CloudBlockBlob 对象。

我正在做的是从 Directory 对象的 ListBlobs() 方法中获取列表,然后遍历列表中的每个项目并将项目转换为 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' 容器中所有 blob 的列表,这些 blob 位于 'natural/landscapes/' 目录路径中,元数据键为 '类别',其值为'日落'”。似乎没有办法做到这一点,这对我来说似乎是一个错失的机会。那好吧。

如果我错了并且离基地很远,请告诉我。

于 2013-01-10T22:13:50.427 回答
6

这种方法是为Java开发的,但我希望可以通过某种方式对其进行修改以适应任何其他受支持的语言。尽管您要求的功能尚未明确开发,但我想我找到了一种不同的(希望不那么笨重)从元素访问CloudBlockBlob数据的方法。ListBlobItem

例如,以下代码可用于删除特定目录中的每个 blob。

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);
}
于 2015-02-11T15:49:27.937 回答
4

前面的答案很好。我只想指出两点:

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)在单独的调用中获取元数据效率不高。该代码为每个 blob 对象发出 2 个 HTTP 请求。ListBlobs() 方法也支持通过设置 BlobListingDetails 参数在一次调用中获取元数据

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

我建议使用第二个代码,这是可能的。因为它是获取元数据的最有效方式。

于 2019-10-16T15:54:37.120 回答