c# - C# sharepoint 循环遍历文件夹和所有子文件夹中的所有文件
问题描述
我试图在一个文件夹中的所有文件和所有子文件夹之后循环,就像它从第一个文件夹开始一样深。我找到了一种方法,但我认为这很愚蠢,可能是一种更好的方法。
代码循环通过第一个文件夹和所有文件。之后,它再次循环子文件夹,然后是文件,然后第三次循环。
还有其他方法可以做到这一点吗?只需选择一个文件夹,然后它会自动向下循环层次结构。
static void ReadAllSubs(string siteUrl, string siteFolderPath, string localTempLocation)
{
ClientContext ctx = new ClientContext(siteUrl);
ctx.AuthenticationMode = ClientAuthenticationMode.Default;
SecureString passWord = new SecureString();
string pwd = "xxx";
foreach (char c in pwd.ToCharArray()) passWord.AppendChar(c);
ctx.Credentials = new SharePointOnlineCredentials("test@test.com", passWord);
FolderCollection folderCollection = ctx.Web.GetFolderByServerRelativeUrl("Delte%20dokumenter/07 - Detaljprosjekt").Folders;
// Don't just load the folder collection, but the property on each folder too
ctx.Load(folderCollection, fs => fs.Include(f => f.ListItemAllFields));
// Actually fetch the data
ctx.ExecuteQuery();
foreach (Folder folder in folderCollection)
{
//LOOP MAIN FOLDER
Console.WriteLine("---------------FIRST LAYER FOLDER---------------------");
var item = folder.ListItemAllFields;
var folderpath = item["FileRef"];
FolderCollection LoopFolder = ctx.Web.GetFolderByServerRelativeUrl(folderpath.ToString()).Folders;
ctx.Load(LoopFolder, fs => fs.Include(f => f.ListItemAllFields));
ctx.ExecuteQuery();
Console.WriteLine(folderpath);
//LOOP ALL FILES IN FIRST MAIN FOLDER
FileCollection mainfiles = ctx.Web.GetFolderByServerRelativeUrl(folderpath.ToString()).Files;
ctx.Load(mainfiles);
ctx.ExecuteQuery();
Console.WriteLine("---------------FIRST LAYER FILES---------------------");
foreach (File mainfile in mainfiles)
{
Console.WriteLine(mainfile.Name);
Console.WriteLine(mainfile.MajorVersion);
}
//LOOP SUBFOLDER
Console.WriteLine("---------------SECOUND LAYER FOLDER---------------------");
foreach (Folder ff in LoopFolder)
{
var subitem = ff.ListItemAllFields;
var folderpathsub = subitem["FileRef"];
Console.WriteLine(folderpathsub);
//LOOP ALL FILES IN FIRST SUBFOLDER
FileCollection files = ctx.Web.GetFolderByServerRelativeUrl(folderpathsub.ToString()).Files;
ctx.Load(files);
ctx.ExecuteQuery();
Console.WriteLine("---------------SECOUND LAYER FILES---------------------");
foreach (File file in files)
{
Console.WriteLine(file.Name);
Console.WriteLine(file.MajorVersion);
}
var created = (DateTime)item["Created"];
var modified = (DateTime)item["Modified"];
Console.WriteLine("---------------THIRD LAYER FOLDER---------------------");
FolderCollection ThirdLoopFolder = ctx.Web.GetFolderByServerRelativeUrl(folderpathsub.ToString()).Folders;
ctx.Load(ThirdLoopFolder, fs => fs.Include(f => f.ListItemAllFields));
ctx.ExecuteQuery();
foreach (Folder fff in ThirdLoopFolder)
{
var item3 = fff.ListItemAllFields;
var folderpath3 = item3["FileRef"];
Console.WriteLine(folderpath3);
//LOOP ALL FILES IN THIRD SUBFOLDER
FileCollection thirdfiles = ctx.Web.GetFolderByServerRelativeUrl(folderpath3.ToString()).Files;
ctx.Load(thirdfiles);
ctx.ExecuteQuery();
Console.WriteLine("---------------THIRD LAYER FILES---------------------");
foreach (File file in thirdfiles)
{
Console.WriteLine(file.Name);
Console.WriteLine(file.MajorVersion);
}
}
}
}
}
解决方案
我可以提出两种解决方案。
第一种方法
第一种是类似于您的解决方案的递归方法。
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 进行身份验证,并从根文件夹(这是库的名称)中获取文件夹。那么第二种方法是递归的。首先从当前文件夹中获取所有文件并将它们打印到控制台,然后下一步是查询该文件夹中的子文件夹,然后执行相同的方法。
第二种方法
第二种方法更“平坦”。可以创建 CAML 查询以递归方式从库中获取所有项目,然后检查它是文件还是文件夹。所有项目都有路径属性来确定层次结构。
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 个查询元素)。在该方法获取所有项目的列表后,它会将它们打印出来,显示路径、文件名和类型(文件或文件夹..或其他..如果没记错的话,这个枚举中可能还有 web 和其他一些)。
对于与第一种方法相同的库这种方法的结果是
希望能帮助到你 :)
推荐阅读
- c# - 运行 UWP 应用程序(C#)时没有显示 StackPanel
- wordpress - 在由 wordpress 进行身份验证之前,首先验证 wordpress 登录凭据到 api
- android - 谷歌地图中绘制多边形线的密钥生成错误
- laravel - 在 Laravel 中使用 FormRequest 自定义 PUT 路由
- c# - C#监控可执行文件的启动并在用户使用它之前执行操作
- sql-server - 如果我想审计我的表,这是一个合适的数据库设计吗?
- c# - 字典默认值作为参数
- swift - UIKit.NSUnderlineStyle single 或 styleSingle
- angular - 用于附加属性的 Typescript 装饰器或继承
- javascript - 下落物体的动画在 IE 上不起作用