2016-03-03 22 views
1

如何列出blob容器中的所有目錄和子目錄?如何使用.NET的Azure存儲客戶端庫列出所有虛擬目錄和子目錄(BLOBS)

這是我到目前爲止有:

public List<CloudBlobDirectory> Folders { get; set; } 

public List<CloudBlobDirectory> GetAllFoldersAndSubFoldersFromBlobStorageContainer() 
{ 
    CloudStorageAccount storageAccount = CloudStorageAccount.Parse(ConfigurationManager.ConnectionStrings["StorageConnectionString"].ConnectionString); 
    CloudBlobClient blobClient = storageAccount.CreateCloudBlobClient(); 
    CloudBlobContainer container = blobClient.GetContainerReference("mycontainer"); 

    if (container.Exists()) 
    { 
     Folders = new List<CloudBlobDirectory>(); 

     foreach (var item in container.ListBlobs()) 
     { 
      if (item is CloudBlobDirectory) 
      { 
       var folder = (CloudBlobDirectory)item; 
       Folders.Add(folder); 
       GetSubFolders(folder); 
      } 
     } 
    } 

    return Folders; 
} 

private void GetSubFolders(CloudBlobDirectory folder) 
{ 
    foreach (var item in folder.ListBlobs()) 
    { 
     if (item is CloudBlobDirectory) 
     { 
      var subfolder = (CloudBlobDirectory)item; 
      Folders.Add(subfolder); 
      GetSubFolders(subfolder); 
     } 
    } 
} 

上面的代碼片段給我我想要的清單,但我不確定遞歸方法和其它.NET/C#語法和最佳實踐編程模式。簡而言之,我希望最終的結果儘可能優雅和高效。

上述代碼片段如何改進?

+0

具體是什麼NuGet包名稱和版本您使用的存儲客戶端?我要求這個重現性 – juvchan

+0
+0

好,我會盡量提供一個基於此解決方案 – juvchan

回答

0

我的功能我用來獲取所有的文件和子目錄。 請注意在運行函數之前分配您BlobContainer對象在構造函數中或其他地方,因此不會叫它爲每個文件/目錄

public IEnumerable<String> getAllFiles(string prefix, bool slash = false) //Prefix for, slash for recur, see folders 
    { 
     List<String> FileList = new List<string>(); 
     if (!BlobContainer.Exists()) return FileList; //BlobContainer is defined in class before this is run 
     var items = BlobContainer.ListBlobs(prefix); 

     foreach (var blob in items) 
     { 
      String FileName = ""; 
      if (blob.GetType() == typeof(CloudBlockBlob)) 
      { 
       FileName = ((CloudBlockBlob)blob).Name; 
       if (slash) FileName.Remove(0, 1); //remove slash if file 
       FileList.Add(FileName); 
      } 
      else if (blob.GetType() == typeof(CloudBlobDirectory)) 
      { 
       FileName = ((CloudBlobDirectory)blob).Prefix; 
       IEnumerable<String> SubFileList = getAllFiles(FileName, true); 
       foreach (String s in SubFileList) 
       { 
        FileList.Add(s); 
       } 
      } 
     } 

     return FileList; 
    } 
+0

謝謝,但它不是真的是我在找什麼。對於我的問題,我有點不清楚,所以對此感到抱歉。我更新了我的問題。 – PussInBoots

3

只有你,否則很優雅的代碼的問題是,它使太多的調用存儲服務來獲取數據。對於每個文件夾/子文件夾,它將轉到存儲服務並獲取數據。

您可以通過列出容器中的所有blob,然後找出它是否是客戶端上的目錄或Blob來避免這種情況。例如,看看這裏的代碼(這不是優雅是你的,但希望它應該給你什麼,我想傳達的想法):

static void FetchCloudBlobDirectories() 
    { 
     var account = new CloudStorageAccount(new StorageCredentials(accountName, accountKey), true); 
     var containerName = "container-name"; 
     var blobClient = account.CreateCloudBlobClient(); 
     var container = blobClient.GetContainerReference(containerName); 
     var containerUrl = container.Uri.AbsoluteUri; 
     BlobContinuationToken token = null; 
     List<string> blobDirectories = new List<string>(); 
     List<CloudBlobDirectory> cloudBlobDirectories = new List<CloudBlobDirectory>(); 
     do 
     { 
      var blobPrefix = "";//We want to fetch all blobs. 
      var useFlatBlobListing = true;//This will ensure all blobs are listed. 
      var blobsListingResult = container.ListBlobsSegmented(blobPrefix, useFlatBlobListing, BlobListingDetails.None, 500, token, null, null); 
      token = blobsListingResult.ContinuationToken; 
      var blobsList = blobsListingResult.Results; 
      foreach (var item in blobsList) 
      { 
       var blobName = (item as CloudBlob).Name; 
       var blobNameArray = blobName.Split(new string[] { "/" }, StringSplitOptions.RemoveEmptyEntries); 
       //If the blob is in a virtual folder/sub folder, it will have a "/" in its name. 
       //By splitting it, we are making sure that it is indeed the case. 
       if (blobNameArray.Length > 1) 
       { 
        StringBuilder sb = new StringBuilder(); 
        //Since the blob name (somefile.png) will be the last element of this array and we're not interested in this, 
        //We only iterate through 2nd last element. 
        for (var i=0; i<blobNameArray.Length-1; i++) 
        { 
         sb.AppendFormat("{0}/", blobNameArray[i]); 
         var blobDirectory = sb.ToString(); 
         if (blobDirectories.IndexOf(blobDirectory) == -1)//We check if we have already added this to our list or not 
         { 
          blobDirectories.Add(blobDirectory); 
          var cloudBlobDirectory = container.GetDirectoryReference(blobDirectory); 
          cloudBlobDirectories.Add(cloudBlobDirectory); 
          Console.WriteLine(cloudBlobDirectory.Uri); 
         } 
        } 
       } 
      } 
     } 
     while (token != null); 
    }