Question

Any help would be appreciated here.

Below is my attempt to copy files and folders from one site collection to a completely different site collection. The structure from one side to the other should be the same for example if /cd/abc/def exists on the source it will be mirrored on the destination site.

My code works for copying folders and documents that exist on the root of the library. But when it encounters a folder that is not on the root or a file that exists inside a sub - sub folder it breaks.

Example Folder /docLibrary/Test works, but /docLibrary/test/test1 copies over as /docLibrary/test1. I know this problem comes from the CopyFolder method calling the folder.Folders.Add method but I'm not sure how to best approach adding a "sub folder" instead of a folder.

I am working with a SharePoint 2019 publishing site and using the Microsoft.SharePoint.Client object.

TLDR: I need to copy all files and folders from a library on one site collection to a library on a completely different site collection that shares the same structure, and I need it to copy sub folders as well. (EnsureFolder doesn't seem to exist in the client context version I'm using)

EDIT 2/3/2020 The marked answer did not quite work, because I couldn't get the MoveCopyUtil to work with multiple contexts, however the second link Clone or Copy SharePoint Document LIbrary had the needed logic. END EDIT

public void CopyDocuments(ClientContext srcContext, ClientContext destContext, string srcLibrary, string destLibrary)
{
    try
    {
        SP.List srcList = srcContext.Web.Lists.GetByTitle(srcLibrary);
        CamlQuery camlQuery = new CamlQuery();
        camlQuery.ViewXml = "<View Scope='RecursiveAll'><Query></Query></View>";
        ListItemCollection collListItems = srcList.GetItems(camlQuery);
        srcContext.Load(collListItems);
        srcContext.ExecuteQuery();
        foreach (ListItem item in collListItems) //Copy folders first 
        {
            try
            {
                if (item.FileSystemObjectType == FileSystemObjectType.Folder)
                {
                    Console.WriteLine("FOLDER FileRef" + item["FileRef"]);
                    CopyFolder(destContext, destLibrary, item);
                }
            }
            catch(Exception ex)
            {
                Console.WriteLine("Copy Documents Error: Copying Folder :" + ex.Message);
            }

        }
        foreach(ListItem item in collListItems) //Copy items next
        {
            try
            {
                if (item.FileSystemObjectType == FileSystemObjectType.File)
                {
                    Console.WriteLine("FILE " + item["FileRef"]);
                    FileInformation fileInformation = SP.File.OpenBinaryDirect(srcContext, item["FileRef"].ToString());
                    srcContext.ExecuteQuery();
                    using (MemoryStream memoryStream = new MemoryStream())
                    {
                        CopyStream(fileInformation.Stream, memoryStream);
                        memoryStream.Seek(0, SeekOrigin.Begin);
                        FileCreationInformation fileCreationInformation = new FileCreationInformation
                        {
                            ContentStream = memoryStream,
                            Overwrite = true,
                            Url = item["FileRef"].ToString()
                        };
                        SP.File uploadFile = destContext.Web.RootFolder.Files.Add(fileCreationInformation);
                        destContext.Load(uploadFile);
                        destContext.ExecuteQuery();
                    }
                }

            }
            catch (Exception ex)
            {
                Console.WriteLine("Copy Documents Error: Copying File :" + ex.Message);
            }
        }
    }
    catch (Exception ex)
    {
        throw ex;
    }
}

private static void CopyFolder(ClientContext destContext, string destLibrary, ListItem item)
{
    List destList = destContext.Web.Lists.GetByTitle(destLibrary);


    Folder folder = destList.RootFolder;            
    destContext.Load(folder);
    folder.Folders.Add(item["FileLeafRef"].ToString());
    //folder.AddSubFolder(item["FileLeafRef"].ToString());
    destContext.ExecuteQuery();
}
static private void CopyStream(Stream source, Stream destination)
{
    byte[] buffer = new byte[32768];
    int bytesRead;
    do
    {
        bytesRead = source.Read(buffer, 0, buffer.Length);
        destination.Write(buffer, 0, bytesRead);
    } while (bytesRead != 0);
}

#endregion
Was it helpful?

Solution

Install the SharePoint 2019 CSOM library using the NuGet below.

Install-Package Microsoft.SharePoint2019.CSOM -Version 16.0.10337.12109

Then use the methods of MoveCopyUtil class to copy/move folders and files.

Example:

string dstUrl = "http://sp2019/sites/team1";
string sourceFolder = "http://sp2019/sites/team1/libraryname/folder1";
string destFolder = dstUrl + "/libraryname/folder1";
using (ClientContext srcContext = new ClientContext(dstUrl))
{
    MoveCopyOptions option = new MoveCopyOptions();
    option.KeepBoth = true;
    MoveCopyUtil.CopyFolder(srcContext, sourceFolder, destFolder, option);
    srcContext.ExecuteQuery();
}

Reference:Copy or Move Folder Structure in SharePoint Using CSOM

Or check the article below with the code to achieve it.

Clone or Copy SharePoint document Library Files and Folders from one site to another using CSOM

Licensed under: CC-BY-SA with attribution
Not affiliated with sharepoint.stackexchange
scroll top