Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C# sharepoint loop through all files in folder and all subfolders

Tags:

c#

sharepoint

I am trying to loop after all files in a folder and all subfolders as deep as it goes from the first folder. I have found a way but I think it's stupid and is probably a way better method to do it.

The code loops through the first folder and all files. After that it loops again the subfolders then files and again for the third time.

Is there some other way I can do this? just choose one folder then it loops down the hierarchy automatically.

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);
                }
            }
        }
    }
}
like image 304
Kickdak Avatar asked Oct 17 '25 18:10

Kickdak


1 Answers

I may propose two solutions.


First method

The first would be a recursive approach similar to Your solution.



    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);
            }
        }
    }


the first function does the authentication to the given WebUrl and gets the folders from the root folder (which is the name of the library). Then the second method is recursive. First gets all files from the current folder and prints them to the console, after that the next step is to query the subfolders in this folder and then do the same method.

I have created a sample library with folders and files and the result of the above method is enter image description here


Second method

The second method is a bit more 'flat'. It is possible to create a CAML query to get all items from library recursively and then check if it's file or folder. All items have path property to determine the hierarchy.



    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();
        }
    }


This method also does the authentication to the same library and then executes a query to get all the items to the list (the Query is done in a pagination way to overcome the threshold limit to get more than 5000 elements in query). After the method gets the list of all items it prints them out presenting the path, name of the file, and type (file or folder.. or other.. If remember well there might be also web and some other in this enum).

For the same library as the first method The result of this approach is

enter image description here


hope it helps :)

like image 185
Adam Avatar answered Oct 20 '25 09:10

Adam



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!