3

I have folder structure like in Shared documents/East using CSOM and C# Main Folder Folder1 Folder2 File1 File2

I have to copy all folders with files to Shared documents/West ....

7

There is no built-in method in SharePoint CSOM API for copying Folder with Files from one location into another.

The following solution demonstrates how to copy files from source folder into destination folder:

public static class FolderExtensions
{


    /// <summary>
    /// Copy files 
    /// </summary>
    /// <param name="folder">Source Folder</param>
    /// <param name="folderUrl">Target Folder Url</param>
    public static void CopyFilesTo(this Folder folder, string folderUrl)
    {
        var ctx = (ClientContext)folder.Context;
        if (!ctx.Web.IsPropertyAvailable("ServerRelativeUrl"))
        {
            ctx.Load(ctx.Web, w => w.ServerRelativeUrl);
        }
        ctx.Load(folder, f => f.Files, f => f.ServerRelativeUrl, f => f.Folders);
        ctx.ExecuteQuery();

        //Ensure target folder exists
        ctx.Web.EnsureFolder(folderUrl.Replace(ctx.Web.ServerRelativeUrl, string.Empty));
        foreach (var file in folder.Files)
        {
            var targetFileUrl = file.ServerRelativeUrl.Replace(folder.ServerRelativeUrl, folderUrl);
            file.CopyTo(targetFileUrl,true);
        }
        ctx.ExecuteQuery();

        foreach (var subFolder in folder.Folders)
        {
            var targetFolderUrl = subFolder.ServerRelativeUrl.Replace(folder.ServerRelativeUrl, folderUrl);
            subFolder.CopyFilesTo(targetFolderUrl);
        }
    }
}

static class WebExtensions
{
    /// <summary>
    /// Ensures whether the folder exists   
    /// </summary>
    /// <param name="web"></param>
    /// <param name="folderUrl"></param>
    /// <returns></returns>
    public static Folder EnsureFolder(this Web web, string folderUrl)
    {
        return EnsureFolderInternal(web.RootFolder, folderUrl);
    }


    private static Folder EnsureFolderInternal(Folder parentFolder, string folderUrl)
    {
        var ctx = parentFolder.Context;
        var folderNames = folderUrl.Split(new char[] { '/' }, StringSplitOptions.RemoveEmptyEntries);
        var folderName = folderNames[0];
        var folder = parentFolder.Folders.Add(folderName);
        ctx.Load(folder);
        ctx.ExecuteQuery();

        if (folderNames.Length > 1)
        {
            var subFolderUrl = string.Join("/", folderNames, 1, folderNames.Length - 1);
            return EnsureFolderInternal(folder, subFolderUrl);
        }
        return folder;
    }
}

Key points:

  • allows to ensure whether target folder(s) exists
  • In case of nested folders, its structure is preserved while copying files

Usage

var srcFolderUrl = "/news/pages"; //News site with Pages library
var destFolderUrl = "/news/archive/pages"; //News archive sub site with Pages library
using (var ctx = new ClientContext(url))
{      
    var sourceFolder = ctx.Web.GetFolderByServerRelativeUrl(srcFolderUrl);
    sourceFolder.CopyFilesTo(destFolderUrl);
}
  • This code unfortunately doesn't make any sense. GetFolderByServerRelativeUrl only works in the context of the web you are trying to get a folder from. folderUrl.Replace(ctx.Web.ServerRelativeUrl, string.Empty) replaces destinationFolderUrl to gibberish. You can not "CopyTo" to another sub site. Have you tried this code before posting? – dotsa Mar 25 '16 at 22:56
4
string siteUrl = "your site url";
    string sourceDirectory = "your source folder";
    string destinationDirectory = "/Shared documents/West";

    using (SPSite currSite = new SPSite(siteUrl))
    {
        using (SPWeb currWeb = currSite.OpenWeb())
        {
            MoveFolder(currWeb, sourceDirectory, destinationDirectory);
        }
    }

    //Move all folders and subfolder
    public void MoveFolder(SPWeb sourceWeb, string sourceDirectory, string destinationDirectory)
    {
        SPFolder srcFolder  = sourceWeb.GetFolder(sourceDirectory);
        if (srcFolder.Exists)
        {
            SPDocumentLibrary docLib = srcFolder.DocumentLibrary;
            SPFolderCollection oFolder = srcFolder.SubFolders;
            SPQuery oQuery = new SPQuery();
            oQuery.Query = "<Where><Eq><FieldRef Name='FSObjType'/><Value Type='Lookup'>1</Value></Eq></Where>";
            oQuery.Folder = oFolder.Folder;
            oQuery.ViewAttributes = "Scope='RecursiveAll'";
            SPListItemCollection collListItems = docLib.GetItems(oQuery);
            string newdestinationFolderPath = destinationDirectory;
            //Move the root folder with files
            MoveSingleFolder(sourceWeb, sourceDirectory, newdestinationFolderPath);

            newdestinationFolderPath = destinationDirectory + "/" + srcFolder.Name;
            //Move the subfolders with files
            foreach (SPListItem item in collListItems)
            {
                MoveSingleFolder(sourceWeb, item.Url, newdestinationFolderPath);
            }
            // Delete the root folder
            DeleteSourceFolder(sourceWeb, sourceDirectory);
        }

    }

    //Move single folder
    private void MoveSingleFolder(SPWeb srcWeb, string sourceFolderPath, string destinationFolderPath)
    {
        SPFolder srcFolder = srcWeb.GetFolder(sourceFolderPath);
        if (srcFolder.Exists)
        {
            string srcFolderName = srcFolder.Name;
            SPFolder dstFolder = srcWeb.GetFolder(destinationFolderPath);
            if (dstFolder.Exists)
            {
                //create the folder
                SPFolder newFolder = dstFolder.SubFolders.Add(srcFolderName);
                    SPListItem newFolderItem = (SPListItem)newFolder.Item;
                    newFolderItem.ParentList.Fields[SPBuiltInFieldId.Modified].ReadOnlyField = false;
                    newFolderItem.ParentList.Fields[SPBuiltInFieldId.Modified_x0020_By].ReadOnlyField = false;
                    newFolderItem[SPBuiltInFieldId.Modified] = srcFolder.Item["Modified"];
                    newFolderItem["Modified By"] = srcFolder.Item["Modified By"];
                    newFolderItem.UpdateOverwriteVersion();
                    newFolderItem.ParentList.Fields[SPBuiltInFieldId.Modified].ReadOnlyField = true;
                    newFolderItem.ParentList.Fields[SPBuiltInFieldId.Modified_x0020_By].ReadOnlyField = true;

            }
            MoveFolderItems(srcWeb, sourceFolderPath, destinationFolderPath + "/" + srcFolderName);
        }
    }

    //Move folder items
    private void MoveFolderItems(SPWeb sourceWeb, string sourceFolderPath, string destinationFolderPath)
    {
        SPFolder srcFolder = sourceWeb.GetFolder(sourceFolderPath);
        int fileCount = srcFolder.Files.Count;
        while (fileCount > 0)
        {
            SPFile sourceFile = sourceWeb.GetFile(srcFolder.Files[0].Url);
            object modifiedOn = sourceFile.Item["Modified"];
            object modifiedBy = sourceFile.Item["Modified By"];

            sourceFile.MoveTo(destinationFolderPath + "/" + sourceFile.Name, true);

            fileCount--;

            SPListItem dstItem = (SPListItem)sourceFile.Item;
            dstItem.ParentList.Fields["Modified"].ReadOnlyField = false;
            dstItem.ParentList.Fields["Modified By"].ReadOnlyField = false;
            dstItem["Modified"] = modifiedOn;
            dstItem["Modified By"] = modifiedBy;
            dstItem.UpdateOverwriteVersion(); //updates the item without creating another version of the item
            dstItem.ParentList.Fields["Modified"].ReadOnlyField = true;
            dstItem.ParentList.Fields["Modified By"].ReadOnlyField = true;
        }
    }

    //Delete the folder
    private void DeleteSourceFolder(SPWeb srcWeb, string sourceFolderPath)
    {
        SPFolder srcFolder = srcWeb.GetFolder(sourceFolderPath);
        if (srcFolder.Exists)
        {
            if (srcFolder.Files.Count == 0) //Delete only after moving
            {
                SPFolder srcRootFolder = srcFolder.ParentFolder;
                srcRootFolder.SubFolders.Delete(srcFolder.Url);
            }
        }

    }
  • 1
    The OP is asking about CSOM solution – Vadim Gremyachev Oct 12 '14 at 19:48
0

The following code will help for your problems :

public static void CopyFiles(string url, string listTitle, string srcFolder,string destFolder)
{
    using (var context = new ClientContext(url))
    {
        //context.Credentials = credentials;


        var srcList = context.Web.Lists.GetByTitle(listTitle);
        var qry = CamlQuery.CreateAllItemsQuery();
        qry.FolderServerRelativeUrl = string.Format("/{0}", srcFolder);
        var srcItems = srcList.GetItems(qry);
        context.Load(srcItems, icol => icol.Include(i => i.FileSystemObjectType, i => i["FileRef"], i => i.File));
        context.ExecuteQuery();

        foreach (var item in srcItems)
        {
            switch (item.FileSystemObjectType)
            {
                case FileSystemObjectType.Folder:
                    var destFolderUrl = ((string)item["FileRef"]).Replace(srcFolder,destFolder);
                    CreateFolder(context.Web,destFolderUrl);
                    break;
                case FileSystemObjectType.File:
                    var destFileUrl = item.File.ServerRelativeUrl.Replace(srcFolder, destFolder);
                    item.File.CopyTo(destFileUrl, true);
                    context.ExecuteQuery();
                    break;
            }
        }
    }
} 

private static Folder CreateFolder(Web web, string folderUrl)
{
    if (string.IsNullOrEmpty(folderUrl))
        throw new ArgumentNullException("Folder Url could not be empty");

    var folder = web.Folders.Add(folderUrl);
    web.Context.Load(folder);
    web.Context.ExecuteQuery();
    return folder;
}

Usage :

CopyFiles("https://contoso.sharepoint.com/", "Shared Documents", "Expense", "Expense 2015");

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.