我试图在文件夹中的所有文件和所有子文件夹中循环播放,其深度与第一个文件夹中的深度相同。我找到了一种方法,但我认为它很愚蠢,并且可能是一种更好的方法。
代码循环遍历第一个文件夹和所有文件。之后,它再次循环子文件夹,然后再循环第三次。
有没有其他方法可以做到这一点?只需选择一个文件夹,然后它会自动向下循环层次结构。
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("[email protected]", 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 和其他一些)。
对于与第一种方法相同的库 这种方法的结果是
希望能帮助到你 :)
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句