Copy Documents between Site Collections in Office 365

In this blog I am going to share the code to copy documents between site collections using CSOM on Office 365 SharePoint. The below code uses the recursive method to get all documents from source site collection and copy it to the target site collection. The script also preserves the modified and modified by details after copying.

In this blog I am using the latest CSOM targeted to Office 365, you can download the latest here

The sample code is in the PowerShell command.  First download the CSOM dll and save it to the folder to be used. The PowerShell command will load the specific dll to use the API.

Add-Type -Path "C:\Microsoft.SharePoint.Client.dll"

Add-Type -Path "C:\Microsoft.SharePoint.Client.Runtime.dll"



$username = "name@domain.com"

$password = "<password here>”

$srcUrl = "<enter the source Url>" ## use the full URL of the site

$destUrl = "<enter the target Url>" ## use the full URL of the site

$srcLibrary = "<Lib Name>"

$destLibrary = "<Target Lib>"

$destinationFolder = "/sites/<SITENAME>/Shared Documents/<folder inside doc lib>/" ## Make sure the folder name ends with /



$securePassword = ConvertTo-SecureString $password -AsPlainText -Force

$credentials = New-Object Microsoft.SharePoint.Client.SharePointOnlineCredentials($username, $securePassword)





function CreateFolders

{

param (

[Parameter(Mandatory=$true)] $srcfolder,

[Parameter(Mandatory=$true)] [string] $destFolderPath

)

Write-Host "Source Folder:" + $srcfolder.Name + " dest folder:" + $destFolderPath -ForegroundColor Yellow

$SPOFolder = $destWeb.GetFolderByServerRelativeUrl($destFolderPath)

$FolderName = $srcfolder.Name

$NewFolder = $SPOFolder.Folders.Add($FolderName)

$destWeb.Context.Load($NewFolder)

$destWeb.Context.ExecuteQuery()

Write-Host "Folder Created - " + $FolderName -ForegroundColor Yellow

## get source folder details

$SrcFolderListItem = $srcfolder.ListItemAllFields

$srcContext.Load($SrcFolderListItem)

$srcContext.ExecuteQuery()

####

$SPOFolderItem = $NewFolder.ListItemAllFields;

$replacedUser =$destWeb.EnsureUser($SrcFolderListItem["Editor"].Email)

$SPOFolderItem["Editor"] = $replacedUser

$replacedUser =$destWeb.EnsureUser($SrcFolderListItem["Author"].Email)

$SPOFolderItem["Author"] = $replacedUser

$SPOFolderItem["Created"] = $SrcFolderListItem["Created"]

$SPOFolderItem["Modified"] = $SrcFolderListItem["Modified"]

$SPOFolderItem.Update()

$destContext.Load($NewFolder)

$destContext.ExecuteQuery()



$fileCol = $srcfolder.Files

$srcContext.Load($fileCol)

$srcContext.ExecuteQuery()

### Load the file to hash table to check with Target library.

$hashFiles = @{}

$DestfileCol = $NewFolder.Files

$destContext.Load($DestfileCol)

$destContext.ExecuteQuery()

foreach ($destFile in $DestfileCol){

$hashFiles.add($destFile.Name,$destFile.Name)

}



foreach ($f in $fileCol)

{

if($hashFiles.ContainsKey($f.Name) -ne "true")

{

$srcContext.Load($f)

$srcContext.ExecuteQuery()

$id = $srcfolder.Name

$nLocation =$NewFolder.ServerRelativeUrl.TrimEnd("/") + "/" + $f.Name

Write-Host $nLocation

try

{

$fileInfo = [Microsoft.SharePoint.Client.File]::OpenBinaryDirect($srcContext, $f.ServerRelativeUrl)

[Microsoft.SharePoint.Client.File]::SaveBinaryDirect($destContext, $nLocation, $fileInfo.Stream,$true)

$ListItem = $f.ListItemAllFields

$srcContext.Load($ListItem)

$srcContext.ExecuteQuery()

$fileCreated = $destWeb.GetFileByServerRelativeUrl($nLocation)

$destContext.Load($fileCreated)

$destContext.ExecuteQuery()

$DestListItem = $fileCreated.ListItemAllFields;

$replacedUser =$destWeb.EnsureUser($ListItem["Editor"].Email)

$DestListItem["Editor"] = $replacedUser

$replacedUser =$destWeb.EnsureUser($ListItem["Author"].Email)

$DestListItem["Author"] = $replacedUser

$DestListItem["Created"] = $ListItem["Created"];

$DestListItem["Modified"] = $ListItem["Modified"];

$DestListItem.Update()

$destContext.Load($fileCreated)

$destContext.ExecuteQuery()

}

catch

{

Write-Host $_ -ForegroundColor Red

}

}

}



$fL1FolderColl = $srcfolder.Folders

$srcContext.Load($fL1FolderColl);

$srcContext.ExecuteQuery();

foreach ($myFolder in $fL1FolderColl)

{

$srcContext.Load($myFolder)

$srcContext.ExecuteQuery()

CreateFolders $myFolder $NewFolder.ServerRelativeUrl

}

}



                                #### The main script starts here ######

$srcContext = New-Object Microsoft.SharePoint.Client.ClientContext($srcUrl)

$srcContext.Credentials = $credentials

$destContext = New-Object Microsoft.SharePoint.Client.ClientContext($destUrl)

$destContext.Credentials = $credentials



$srcWeb = $srcContext.Web

$srcList = $srcWeb.Lists.GetByTitle($srcLibrary)

$query = New-Object Microsoft.SharePoint.Client.CamlQuery

$listItems = $srcList.GetItems($query)

$srcContext.Load($srcList)

$srcContext.Load($listItems)

$srcContext.ExecuteQuery()



$destWeb = $destContext.Web

$destList = $destWeb.Lists.GetByTitle($destLibrary)

$destContext.Load($destWeb)

$destContext.Load($destList)

$destContext.ExecuteQuery()







########### this is to copy only certain folders

#$folder = $srcWeb.GetFolderByServerRelativeUrl($srcFolder)

#$srcContext.Load($folder)

#$srcContext.ExecuteQuery()

#Write-Host $destinationFolder

#CreateFolders $folder $destinationFolder

##############



foreach($item in $listItems)

{

if($item.FileSystemObjectType -eq "File")

{

#$srcContext.Load($item)

#$srcContext.ExecuteQuery()

$srcF = $item.File

$srcContext.Load($srcF)

$srcContext.ExecuteQuery()

$rootLocation = $destinationFolder + $srcF.Name

Write-Host $rootLocation

$fileContent = [Microsoft.SharePoint.Client.File]::OpenBinaryDirect($srcContext, $srcF.ServerRelativeUrl)

[Microsoft.SharePoint.Client.File]::SaveBinaryDirect($destContext, $rootLocation, $fileContent.Stream,$true)

$fItem = $srcF.ListItemAllFields

$srcContext.Load($fItem)

$srcContext.ExecuteQuery()



$fCreated = $destWeb.GetFileByServerRelativeUrl($rootLocation)

$destContext.Load($fCreated)

$destContext.ExecuteQuery()



$DListItem = $fCreated.ListItemAllFields;

$replacedUser =$destWeb.EnsureUser($fItem["Editor"].Email)

$DListItem["Editor"] = $replacedUser

$replacedUser =$destWeb.EnsureUser($fItem["Author"].Email)

$DListItem["Author"] = $replacedUser

$DListItem["Created"] = $fItem["Created"];

$DListItem["Modified"] = $fItem["Modified"];

$DListItem.Update()

$destContext.Load($fCreated)

$destContext.ExecuteQuery()



}

elseif ($item.FileSystemObjectType -eq "Folder")

{

$srcContext.Load($item)

$srcContext.ExecuteQuery()

$folder = $srcWeb.GetFolderByServerRelativeUrl($item.FieldValues["FileRef"].ToString())

$srcContext.Load($folder)

$srcContext.ExecuteQuery()

##################

Write-Host $destinationFolder

CreateFolders $folder $destinationFolder

}

}



Write-Host “Script End”
Senthamil discusses Site collections

Senthamil discusses Site collections

About the Author: 

Senthamil Selvan is an Microsoft MVP in Windows Development. He has 11+ years of experience in Microsoft Platform including Windows Forms, SharePoint and Universal Apps development. He has published several Windows 8 and Windows Phone 8 Apps in the Store. Below are some of his Windows Phone Apps:1.Math Formulas2.Animal Taxonomy3.IUPAC4.SG Parking5.Mani Samayal6.Ultimate Cryptex7.SEA SPC 20148.SCU APAC 2015Windows 8 Apps include:1.Mathematic Formulas2.Ultimate Player3.SG Things To do4.Ultimate Cryptex.5.SEA SPC 2014.

Follow Senthamil on Twitter: @ALTFO

Share this on...

Rate this Post:

Share: