Я могу предложить два решения.
Первый метод
Первый - это рекурсивный подход, аналогичный Вашему решению.
private static void UseRecursiveMethodToGetAllItems()
{
using (var context = new ClientContext(WebUrl))
{
context.Credentials = new SharePointOnlineCredentials(UserName, Password);
var rootFolders = context.Web.GetFolderByServerRelativeUrl(LibName).Folders;
context.Load(rootFolders, folders => folders.Include(f => f.ListItemAllFields));
context.ExecuteQuery();
foreach (var folder in rootFolders)
{
GetFilesAndFolders(context, folder);
}
Console.ReadLine();
}
}
private static void GetFilesAndFolders(ClientContext context, Folder folder)
{
if (folder != null && folder.ListItemAllFields.FieldValues.Count > 0)
{
Console.WriteLine($"Folder - {folder.ListItemAllFields.FieldValues["FileLeafRef"]}");
var fileCollection = folder.Files;
context.Load(fileCollection, files => files.Include(f => f.ListItemAllFields));
context.ExecuteQuery();
foreach(var file in fileCollection)
{
Console.WriteLine($" -> {file.ListItemAllFields.FieldValues["FileLeafRef"]}");
}
var subFolderCollection = folder.Folders;
context.Load(subFolderCollection, folders => folders.Include(f => f.ListItemAllFields));
context.ExecuteQuery();
foreach (var subFolder in subFolderCollection)
{
GetFilesAndFolders(context, subFolder);
}
}
}
первая функция выполняет аутентификацию в указанный WebUrl и получает папки из папки root (которая является названием библиотеки). Тогда второй метод является рекурсивным. Сначала получает все файлы из текущей папки и печатает их на консоли, после чего следующим шагом является запрос вложенных папок в этой папке, а затем выполнить тот же метод.
Я создал библиотеку образцов с папками и файлами, и результатом вышеупомянутого метода является
Второй метод
Второй метод немного более «плоский». Можно создать запрос CAML, чтобы рекурсивно получить все элементы из библиотеки, а затем проверить, является ли он файлом или папкой. Все элементы имеют свойство path для определения иерархии.
private static void UseQueryToGetAllItems()
{
using (var context = new ClientContext(WebUrl))
{
context.Credentials = new SharePointOnlineCredentials(UserName, Password);
List<ListItem> result = new List<ListItem>();
try
{
ListItemCollectionPosition position = null;
int page = 1;
do
{
List list = context.Web.Lists.GetByTitle(LibName);
CamlQuery query = new CamlQuery();
query.ViewXml = new StringBuilder()
.Append("<View Scope=\"RecursiveAll\">")
.Append("<Query>")
.Append("")
.Append("</Query>")
.Append("<RowLimit>5000</RowLimit>")
.Append("</View>")
.ToString();
query.ListItemCollectionPosition = position;
ListItemCollection items = list.GetItems(query);
context.Load(items);
context.ExecuteQuery();
position = items.ListItemCollectionPosition;
if (items.Count > 0)
result.AddRange(items);
context.ExecuteQuery();
page++;
}
while (position != null);
result.ForEach(item =>
{
Console.WriteLine($"{item["ID"]}) Path: {item["FileDirRef"]} - Name: {item["FileLeafRef"]} - Type: {item.FileSystemObjectType}");
});
}
catch (Exception ex)
{
Console.WriteLine(ex);
}
Console.ReadLine();
}
}
Этот метод также выполняет проверку подлинности для той же библиотеки, а затем выполняет запрос для получения всех элементов в списке (запрос выполняется в пагинации способ преодоления порогового значения для получения более 5000 элементов в запросе). После того, как метод получает список всех элементов, он распечатывает их, представляя путь, имя файла и тип (файл или папка ... или другое .. Если хорошо помните, в этом перечислении могут быть также сеть и некоторые другие).
Для той же библиотеки, что и первый метод. Результатом этого подхода является
надеюсь, это поможет:)