如何递归加载 Azure blob 文件列表?
How to load list of Azure blob files recursively?
Azure blob 文件存储在没有任何物理文件夹结构的普通列表中,但我们可以创建虚拟文件夹,其中每个文件的文件夹路径都是其名称的一部分。
这带来了另一个问题,如何仅使用该文件夹的名称来检索虚拟子文件夹中所有文件的列表?
此静态 class BlobHelper
将加载给定 blob 文件夹及其所有子文件夹中的所有 blob 文件的列表。
就这样称呼它:
var blobs = BlobHelper.ListFolderBlobs("blob-container-name", "container-directory");
这里是完整的BlobHelper
代码:
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using Microsoft.WindowsAzure;
using Microsoft.WindowsAzure.Storage;
using Microsoft.WindowsAzure.Storage.Blob;
// Class to contain list of blob files info
public class BlobFileInfo {
public string FileName { get; set; }
public string BlobPath { get; set; }
public string BlobFilePath { get; set; }
public IListBlobItem Blob { get; set; }
}
public static class BlobHelper {
// Load blob container
public static CloudBlobContainer GetBlobContainer(string containerName) {
var storageAccount = CloudStorageAccount.Parse(CloudConfigurationManager.GetSetting("StorageConnectionString"));
var blobClient = storageAccount.CreateCloudBlobClient();
var container = blobClient.GetContainerReference(containerName);
return container;
}
// Get recursive list of files
public static IEnumerable<BlobFileInfo> ListFolderBlobs(string containerName, string directoryName) {
var blobContainer = GetBlobContainer(containerName);
var blobDirectory = blobContainer.GetDirectoryReference(directoryName);
var blobInfos = new List<BlobFileInfo>();
var blobs = blobDirectory.ListBlobs().ToList();
foreach (var blob in blobs) {
if (blob is CloudBlockBlob) {
var blobFileName = blob.Uri.Segments.Last().Replace("%20", " ");
var blobFilePath = blob.Uri.AbsolutePath.Replace(blob.Container.Uri.AbsolutePath + "/", "").Replace("%20", " ");
var blobPath = blobFilePath.Replace("/" + blobFileName, "");
blobInfos.Add(new BlobFileInfo {
FileName = blobFileName,
BlobPath = blobPath,
BlobFilePath = blobFilePath,
Blob = blob
});
}
if (blob is CloudBlobDirectory) {
var blobDir = blob.Uri.OriginalString.Replace(blob.Container.Uri.OriginalString + "/", "");
blobDir = blobDir.Remove(blobDir.Length - 1);
var subBlobs = ListFolderBlobs(containerName, blobDir);
blobInfos.AddRange(subBlobs);
}
}
return blobInfos;
}
}
实际上,有一种更简单的方法可以做到这一点,并且它在库本身中可用。如果您查看 CloudBlobContainer.ListBlobs
方法,它接受两个参数:
- prefix:这是您的目录名称。如果它是嵌套目录,则需要指定完整路径,例如myfolder/mysubfolder.
useFlatBlobListing:将此值设置为 true
将确保仅返回 blob(包括该目录内的任何子文件夹内)而不返回目录和 blob。
var account = new CloudStorageAccount(new StorageCredentials(accountName, accountKey), true);
var blobClient = account.CreateCloudBlobClient();
var container = blobClient.GetContainerReference("blob-container-name");
var blobs = container.ListBlobs(prefix: "container-directory", useFlatBlobListing: true);
您将获得属于 blobs
变量中 "container-directory" 的所有 blob 的列表。
根据 Gaurav Mantri 的回答,这是一种将文件递归显示为层次结构的简单方法。
public class UriNode
{
public Uri ThisUri { get; private set; }
public IEnumerable<UriNode> Children { get; private set; }
public UriNode(CloudBlobContainer container, Uri thisUri = null)
{
ThisUri = thisUri;
if (ThisUri == null)
{
Children = container.ListBlobs().Select(b => new UriNode(container, b.Uri));
return;
}
if (!new Regex(@"\/$").IsMatch(ThisUri.AbsolutePath)) return;
var prefix = string.Join("/", ThisUri.Segments.Skip(2).Take(ThisUri.Segments.Length - 2));
Children = container.ListBlobs(prefix).Select(b => new UriNode(container, b.Uri));
}
}
用法:
new UriNode(container);
Azure blob 文件存储在没有任何物理文件夹结构的普通列表中,但我们可以创建虚拟文件夹,其中每个文件的文件夹路径都是其名称的一部分。
这带来了另一个问题,如何仅使用该文件夹的名称来检索虚拟子文件夹中所有文件的列表?
此静态 class BlobHelper
将加载给定 blob 文件夹及其所有子文件夹中的所有 blob 文件的列表。
就这样称呼它:
var blobs = BlobHelper.ListFolderBlobs("blob-container-name", "container-directory");
这里是完整的BlobHelper
代码:
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using Microsoft.WindowsAzure;
using Microsoft.WindowsAzure.Storage;
using Microsoft.WindowsAzure.Storage.Blob;
// Class to contain list of blob files info
public class BlobFileInfo {
public string FileName { get; set; }
public string BlobPath { get; set; }
public string BlobFilePath { get; set; }
public IListBlobItem Blob { get; set; }
}
public static class BlobHelper {
// Load blob container
public static CloudBlobContainer GetBlobContainer(string containerName) {
var storageAccount = CloudStorageAccount.Parse(CloudConfigurationManager.GetSetting("StorageConnectionString"));
var blobClient = storageAccount.CreateCloudBlobClient();
var container = blobClient.GetContainerReference(containerName);
return container;
}
// Get recursive list of files
public static IEnumerable<BlobFileInfo> ListFolderBlobs(string containerName, string directoryName) {
var blobContainer = GetBlobContainer(containerName);
var blobDirectory = blobContainer.GetDirectoryReference(directoryName);
var blobInfos = new List<BlobFileInfo>();
var blobs = blobDirectory.ListBlobs().ToList();
foreach (var blob in blobs) {
if (blob is CloudBlockBlob) {
var blobFileName = blob.Uri.Segments.Last().Replace("%20", " ");
var blobFilePath = blob.Uri.AbsolutePath.Replace(blob.Container.Uri.AbsolutePath + "/", "").Replace("%20", " ");
var blobPath = blobFilePath.Replace("/" + blobFileName, "");
blobInfos.Add(new BlobFileInfo {
FileName = blobFileName,
BlobPath = blobPath,
BlobFilePath = blobFilePath,
Blob = blob
});
}
if (blob is CloudBlobDirectory) {
var blobDir = blob.Uri.OriginalString.Replace(blob.Container.Uri.OriginalString + "/", "");
blobDir = blobDir.Remove(blobDir.Length - 1);
var subBlobs = ListFolderBlobs(containerName, blobDir);
blobInfos.AddRange(subBlobs);
}
}
return blobInfos;
}
}
实际上,有一种更简单的方法可以做到这一点,并且它在库本身中可用。如果您查看 CloudBlobContainer.ListBlobs
方法,它接受两个参数:
- prefix:这是您的目录名称。如果它是嵌套目录,则需要指定完整路径,例如myfolder/mysubfolder.
useFlatBlobListing:将此值设置为
true
将确保仅返回 blob(包括该目录内的任何子文件夹内)而不返回目录和 blob。var account = new CloudStorageAccount(new StorageCredentials(accountName, accountKey), true); var blobClient = account.CreateCloudBlobClient(); var container = blobClient.GetContainerReference("blob-container-name"); var blobs = container.ListBlobs(prefix: "container-directory", useFlatBlobListing: true);
您将获得属于 blobs
变量中 "container-directory" 的所有 blob 的列表。
根据 Gaurav Mantri 的回答,这是一种将文件递归显示为层次结构的简单方法。
public class UriNode
{
public Uri ThisUri { get; private set; }
public IEnumerable<UriNode> Children { get; private set; }
public UriNode(CloudBlobContainer container, Uri thisUri = null)
{
ThisUri = thisUri;
if (ThisUri == null)
{
Children = container.ListBlobs().Select(b => new UriNode(container, b.Uri));
return;
}
if (!new Regex(@"\/$").IsMatch(ThisUri.AbsolutePath)) return;
var prefix = string.Join("/", ThisUri.Segments.Skip(2).Take(ThisUri.Segments.Length - 2));
Children = container.ListBlobs(prefix).Select(b => new UriNode(container, b.Uri));
}
}
用法:
new UriNode(container);