Проверка вашего запроса LINQ:
var size = directory
.ListFilesAndDirectories()
.Select(x => (CloudFileDirectory)x)
.SelectMany(x => x.ListFilesAndDirectories())
.Sum(x => ((CloudFile)x).Properties.Length);
Я вижу некоторые начальные проблемы. Во-первых, предполагается, что только каталоги будут существовать на первом уровне внутри каталога root. Это можно увидеть с помощью кастинга (CloudFileDirectory)x
. Это вызовет исключение, если вместо этого будет найдено CloudFile
. Масштабируемое решение должно обрабатывать оба типа файлов. Во-вторых, этот запрос также предполагает, что в каждом дочернем каталоге будут существовать только файлы, следовательно, приведение (CloudFile)x
. Это означает, что это будет только go один уровень глубоко внутри дочерних каталогов, и не будет проходить через любые подкаталоги. Это также вызовет исключение, если вместо этого будут найдены какие-либо подкаталоги. Я изложил некоторые более масштабируемые подходы ниже.
Решение 1:
Используйте CloudFileDirectory.ListFilesAndDirectories()
, который объединяет все файлы в IEnumerable<IListFileItem>
. Рекурсивно go просматривайте каждый элемент и суммируйте найденные файлы, если файл найден, или рекурсивно, если каталог найден.
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;
}
}
}
Использование 1:
long bytesCount = 0;
FileShareByteCount(sampleDir, ref bytesCount);
Console.WriteLine($"Current file share usage: {bytesCount}");
Решение 2:
Go через файлообмен в пакетном режиме используя CloudFileDirectory.ListFilesAndDirectoriesSegmented()
, что позволяет вам указать количество файлов, которые должны быть возвращены на сегмент IEnumerable<IListFileItem>
. То же, что и выше, рекурсивно go для каждого элемента и суммирования найденных файлов, если файл найден, или повторное вычисление, если каталог найден.
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.