将SharePoint文件夹和内容移动到同一文档库中的不同位置

本文关键字:文档 位置 文件夹 SharePoint 移动 | 更新日期: 2023-09-27 18:26:12

我正在寻找一种方法,使用SharePoint 2010客户端对象模型(C#)将文件夹及其所有内容移动到同一库中的不同位置。

例如,我们有一个项目的文件夹(比如12345),它的URL是

http://sharepoint/site/library/2012/12345

其中2012代表一年。我想通过编程将12345文件夹移到另一个年份,比如2014年,它可能已经存在,但可能还没有。

我到处搜索过,但我得到的解决方案似乎非常复杂,而且与将文件夹移动到不同的网站集有关,我希望因为它在同一个库中,所以可能有一个更简单的解决方案?我的一个想法是依赖Explorer View而不是CSOM?

非常感谢!

将SharePoint文件夹和内容移动到同一文档库中的不同位置

在SharePoint CSOM API中没有内置的方法将带有文件的文件夹从一个位置移动到另一个位置。

以下类表示如何将文件从源文件夹移动到目标文件夹:

public static class FolderExtensions
{

    public static void MoveFilesTo(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
        EnsureFolder(ctx.Web.RootFolder, folderUrl.Replace(ctx.Web.ServerRelativeUrl, string.Empty));
        foreach (var file in folder.Files)
        {
            var targetFileUrl = file.ServerRelativeUrl.Replace(folder.ServerRelativeUrl, folderUrl);
            file.MoveTo(targetFileUrl, MoveOperations.Overwrite);
        }
        ctx.ExecuteQuery();
        foreach (var subFolder in folder.Folders)
        {
            var targetFolderUrl = subFolder.ServerRelativeUrl.Replace(folder.ServerRelativeUrl,folderUrl);
            subFolder.MoveFilesTo(targetFolderUrl);
        }
    }

    public static Folder EnsureFolder(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 EnsureFolder(folder, subFolderUrl);
        }
        return folder;
    }
}

要点:

  • 允许确保目标文件夹是否存在
  • 如果是嵌套文件夹,则在移动文件时会保留其结构

用法

var srcFolderUrl = "/news/pages";
var destFolderUrl = "/news/archive/pages";
using (var ctx = new ClientContext(url))
{      
    var sourceFolder = ctx.Web.GetFolderByServerRelativeUrl(srcFolderUrl);
    sourceFolder.MoveFilesTo(destFolderUrl);
    sourceFolder.DeleteObject(); // delete source folder if nessesary
    ctx.ExecuteQuery();
}

以防万一有人需要将其转换为PnP PowerShell。它没有经过战斗测试,但对我有效。版本和元数据也在同一个库中移动。

$list = Get-PnPList -Identity Documents
$web = $list.ParentWeb
$folder = Ensure-PnPFolder -Web $list.ParentWeb -SiteRelativePath "Shared Documents/MoveTo"
$tofolder = Ensure-PnPFolder -Web $list.ParentWeb -SiteRelativePath "Shared Documents/MoveTwo"
function MoveFolder
{
    [cmdletbinding()]
    Param (
        $web,
        $fromFolder,
        $toFolder
    )
    $fromFolder.Context.Load($fromFolder.Files)
    $fromFolder.Context.Load($fromFolder.Folders)
    $fromFolder.Context.ExecuteQuery()
    foreach ($file in $fromFolder.Files)
    {
        $targetFileUrl = $file.ServerRelativeUrl.Replace($fromFolder.ServerRelativeUrl, $toFolder.ServerRelativeUrl);
        $file.MoveTo($targetFileUrl, [Microsoft.SharePoint.Client.MoveOperations]::Overwrite);
    }
    $fromFolder.Context.ExecuteQuery();
    foreach ($subFolder in $fromFolder.Folders)
    {
        $targetFolderUrl = $subFolder.ServerRelativeUrl.Replace($fromFolder.ServerRelativeUrl, $toFolder.ServerRelativeUrl);
        $targetFolderRelativePath = $targetFolderUrl.SubString($web.RootFolder.ServerRelativeUrl.Length)
        $tofolder = Ensure-PnPFolder -Web $list.ParentWeb -SiteRelativePath $targetFolderRelativePath
        MoveFolder -Web $web -fromFolder $subFolder -toFolder $tofolder
    }
}
$web.Context.Load($web.RootFolder)
$web.Context.ExecuteQuery()
MoveFolder -Web $web -fromFolder $folder -toFolder $tofolder
$folder.DeleteObject()
$web.Context.ExecuteQuery()