簡體   English   中英

Asp.Net Azure Cloud - 獲取文件大小需要很長時間

[英]Asp.Net Azure Cloud - Getting files size takes long time

我想獲得父文件夾下可用的各種子文件夾下所有文件的大小總和。

我得到了大小,但計算結果大約需要 15 秒。

這是代碼:

var storageAccount = CloudStorageAccount.Parse("connectionString");
var fileClient = storageAccount.CreateCloudFileClient();
var cloudFileShare = fileClient.GetShareReference("shareName");
var rootDirectory = cloudFileShare.GetRootDirectoryReference();
var directory = rootDirectory.GetDirectoryReference("folderName");

var size = directory.ListFilesAndDirectories().Select(x => (CloudFileDirectory)x).SelectMany(x => x.ListFilesAndDirectories()).Sum(x => ((CloudFile)x).Properties.Length);

我可以進一步優化它以快速獲得尺寸嗎?

編輯1:

測試:

  • 場景 1:包含更多或更少文件的更多文件夾
  • 場景 2:文件夾更少,文件更多或更少

發現:

  • 無論文件數量如何(可能更多或更少),當文件夾數更多時需要很長時間
  • 當文件夾數量較少時,它工作正常,而不管文件數量(可能更多或更少)

檢查您的 LINQ 查詢:

var size = directory
           .ListFilesAndDirectories()
           .Select(x => (CloudFileDirectory)x)
           .SelectMany(x => x.ListFilesAndDirectories())
           .Sum(x => ((CloudFile)x).Properties.Length);

我可以看到一些初始問題。 首先,這假設根目錄中的第一級僅存在目錄。 這可以通過轉換(CloudFileDirectory)x看到。 如果找到CloudFile這將引發異常。 可擴展的解決方案應該處理這兩種類型的文件。 其次,這個查詢還假設每個子目錄中只存在文件,因此(CloudFile)x轉換。 這意味着這只會在子目錄中深入一層,並且不會遍歷任何子目錄。 如果找到任何子目錄,這也會引發異常。 我在下面概述了一些更具可擴展性的方法。

解決方案1:

使用CloudFileDirectory.ListFilesAndDirectories() ,它將所有文件組合成一個IEnumerable<IListFileItem> 如果找到文件,則遞歸遍歷每個項目並總結找到的 btyes,如果找到目錄,則遞歸。

public static void FileShareByteCount(CloudFileDirectory directory, ref long bytesCount)
{
    if (directory == null)
    {
        throw new ArgumentNullException("directory", "Directory cannot be null");
    }

    var files = directory.ListFilesAndDirectories();

    foreach (var item in files)
    {
        if (item.GetType() == typeof(CloudFileDirectory))
        {
            var cloudFileDirectory = item as CloudFileDirectory;
            FileShareByteCount(cloudFileDirectory, ref bytesCount);
        }
        else if (item.GetType() == typeof(CloudFile))
        {
            var cloudFile = item as CloudFile;
            bytesCount += cloudFile.Properties.Length;
        }
    }
}

用法一:

long bytesCount = 0;
FileShareByteCount(sampleDir, ref bytesCount);
Console.WriteLine($"Current file share usage: {bytesCount}");

解決方案2:

使用CloudFileDirectory.ListFilesAndDirectoriesSegmented()分批瀏覽文件共享,它允許您指定每個IEnumerable<IListFileItem>段要返回的文件數。 同上,遞歸遍歷每一項並在找到文件時總結找到的字節數,如果找到目錄則遞歸。

public static void FileShareByteCount(CloudFileDirectory directory, int? maxResults, ref long bytesCount)
{
    if (directory == null)
    {
        throw new ArgumentNullException("directory", "Directory cannot be null");
    }

    FileContinuationToken continuationToken = null;

    do
    {
        var resultSegment = directory.ListFilesAndDirectoriesSegmented(maxResults, continuationToken, null, null);

        var results = resultSegment.Results;

        if (results.Count() > 0)
        {
            foreach (var item in results)
            {
                if (item.GetType() == typeof(CloudFileDirectory))
                {
                    var cloudFileDirectory = item as CloudFileDirectory;
                    FileShareByteCount(cloudFileDirectory, maxResults, ref bytesCount);
                }
                else if (item.GetType() == typeof(CloudFile))
                {
                    var cloudFile = item as CloudFile;
                    bytesCount += cloudFile.Properties.Length;
                }
            }
        }

        continuationToken = resultSegment.ContinuationToken;

    } while (continuationToken != null);
}

用法2:

long bytesCount = 0;
FileShareByteCount(directory, 100, ref bytesCount);
Console.WriteLine($"Current file share usage: {bytesCount}");

注意:您可以使用maxResults指定段的最大大小。 Microsoft 文檔指出:

一個非負整數值,表示一次返回的最大結果數,最多為每次操作限制 5000。如果此值為空,則將返回最大可能的結果數,最多為 5000。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM