首页 > 解决方案 > 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);
                }
            }
        }
    }
}

标签: c#sharepoint

解决方案


我可以提出两种解决方案。


第一种方法

第一种是类似于您的解决方案的递归方法。



    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 和其他一些)。

对于与第一种方法相同的库这种方法的结果是

在此处输入图像描述


希望能帮助到你 :)


推荐阅读