Overview
Being one of the most common questions “How to upload files to SharePoint Library?”, i noticed that usually folder structure is not taken into account in the provided solutions.
So i decided to fill the gap and implement another version that allows to preserve folder structure while uploading files.
Prerequisites
- SharePoint client components SDK have to be installed on the machine running the script
PowerShell script
PowerShell script demonstrates how to upload files within a specified local directory to a Document Library within a Site in an O365 tenant.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Add-Type –Path "C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\15\ISAPI\Microsoft.SharePoint.Client.dll" | |
Add-Type –Path "C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\15\ISAPI\Microsoft.SharePoint.Client.Runtime.dll" | |
Function Ensure-Folder() | |
{ | |
Param( | |
[Parameter(Mandatory=$True)] | |
[Microsoft.SharePoint.Client.Web]$Web, | |
[Parameter(Mandatory=$True)] | |
[Microsoft.SharePoint.Client.Folder]$ParentFolder, | |
[Parameter(Mandatory=$True)] | |
[String]$FolderUrl | |
) | |
$folderNames = $FolderUrl.Trim().Split("/",[System.StringSplitOptions]::RemoveEmptyEntries) | |
$folderName = $folderNames[0] | |
Write-Host "Creating folder [$folderName] …" | |
$curFolder = $ParentFolder.Folders.Add($folderName) | |
$Web.Context.Load($curFolder) | |
$web.Context.ExecuteQuery() | |
Write-Host "Folder [$folderName] has been created succesfully. Url: $($curFolder.ServerRelativeUrl)" | |
if ($folderNames.Length -gt 1) | |
{ | |
$curFolderUrl = [System.String]::Join("/", $folderNames, 1, $folderNames.Length – 1) | |
Ensure–Folder –Web $Web –ParentFolder $curFolder –FolderUrl $curFolderUrl | |
} | |
} | |
Function Upload-File() | |
{ | |
Param( | |
[Parameter(Mandatory=$True)] | |
[Microsoft.SharePoint.Client.Web]$Web, | |
[Parameter(Mandatory=$True)] | |
[String]$FolderRelativeUrl, | |
[Parameter(Mandatory=$True)] | |
[System.IO.FileInfo]$LocalFile | |
) | |
try { | |
$fileUrl = $FolderRelativeUrl + "/" + $LocalFile.Name | |
Write-Host "Uploading file [$($LocalFile.FullName)] …" | |
[Microsoft.SharePoint.Client.File]::SaveBinaryDirect($Web.Context, $fileUrl, $LocalFile.OpenRead(), $true) | |
Write-Host "File [$($LocalFile.FullName)] has been uploaded succesfully. Url: $fileUrl" | |
} | |
catch { | |
write-host "An error occured while uploading file [$($LocalFile.FullName)]" | |
} | |
} | |
function Upload-Files() | |
{ | |
Param( | |
[Parameter(Mandatory=$True)] | |
[String]$Url, | |
[Parameter(Mandatory=$True)] | |
[String]$UserName, | |
[Parameter(Mandatory=$False)] | |
[String]$Password, | |
[Parameter(Mandatory=$True)] | |
[String]$TargetListTitle, | |
[Parameter(Mandatory=$True)] | |
[String]$SourceFolderPath | |
) | |
if($Password) { | |
$SecurePassword = $Password | ConvertTo-SecureString –AsPlainText –Force | |
} | |
else { | |
$SecurePassword = Read-Host –Prompt "Enter the password" –AsSecureString | |
} | |
$Context = New-Object Microsoft.SharePoint.Client.ClientContext($Url) | |
$Credentials = New-Object Microsoft.SharePoint.Client.SharePointOnlineCredentials($UserName,$SecurePassword) | |
$Context.Credentials = $Credentials | |
$web = $Context.Web | |
$Context.Load($web) | |
$list = $web.Lists.GetByTitle($TargetListTitle); | |
$Context.Load($list.RootFolder) | |
$Context.ExecuteQuery() | |
Get-ChildItem $SourceFolderPath –Recurse | % { | |
if ($_.PSIsContainer -eq $True) { | |
$folderUrl = $_.FullName.Replace($SourceFolderPath,"").Replace("\","/") | |
if($folderUrl) { | |
Ensure–Folder –Web $web –ParentFolder $list.RootFolder –FolderUrl $folderUrl | |
} | |
} | |
else{ | |
$folderRelativeUrl = $list.RootFolder.ServerRelativeUrl + $_.DirectoryName.Replace($SourceFolderPath,"").Replace("\","/") | |
Upload–File –Web $web –FolderRelativeUrl $folderRelativeUrl –LocalFile $_ | |
} | |
} | |
} | |
#Usage | |
$Url = "https://contoso.sharepoint.com" | |
$UserName = "username@contoso.onmicrosoft.com" | |
$Password = "password" | |
$TargetListTitle = "Documents" #Target Library | |
$SourceFolderPath = "C:\Users\user\Upload" #Source Physical Path | |
#Upload files | |
Upload–Files –Url $Url –UserName $UserName –Password $Password –TargetListTitle $TargetListTitle –SourceFolderPath $SourceFolderPath |
Great script, but don’t forget to close the stream:
$FileStream = $LocalFile.OpenRead();
[Microsoft.SharePoint.Client.File]::SaveBinaryDirect($Web.Context, $fileUrl, $FileStream, $true)
$FileStream.Close();
Thanks for the tip!
i tried to use this script but i got an error. it says that “Documents” does not exist. as i have checked, Document library folder exist on my SharePoint account.
If your native language is different than English try typing “documents” in your own language that worked for me.
Thanks for the script it’s great. I am trying to figure out how to start the import one level deeper and wonder if had a tip? So not at the root level context but starting at a sub-folder? Thanks!
Hello, sorry if out the topic, in fact I’m stuck with this issue for multiple days…
I encounter some trouble uploading file to sp 365 usin curl with php. I cannot send metadata when sending the file. Perhaps somebody would help me on this?
If you feel want to help me please have a look at the end of this page ( my name: ‘csi’ ):
https://blog.vgrem.com/2014/05/31/sharepoint-online-client-php/#comment-6123
Kind regards.
Claude
When i attempt to upload to sharepoint online, I can create the folder structure but no documents will create. I’ve tried running as administrator and normal user, The account I’m using on the sharepoint online is the site owner so doesnt have the required permissions.
I need to do this for a OneDrive migration, but what I want is to create a folder called “Archive” and then copy all the content into that folder so users don’t get cluttered with old content. Any clues? I’m OK with Powershell generally but only just started looking as Sharepoint, CSOM, etc.
My workaround at present for this is to move the existing HomeDrive content into a “Archive” folder at the source using standard file operations I understand, but this isn’t ideal.
Great script, thanks for sharing!
Fantastic script, has helped a lot migrating from file share to OneDrive for Business. Thanks!
Thanks!!! This script is just what I needed.
Thanks for sharing!
Excellect script
Great script ! how can i modify it to upload to a folder within a library?
I am getting error as
Exception calling “ExecuteQuery” with “0” argument(s): “The sign-in name or password does not match one in the Microsoft account system.”
But the account do exists.
The account is working if I login through webportal.
I am also getting the same error. How to fix this. Credentials are working through web portal but not via script..
Great!Great and again Great!Thanks!
Thanks. I would like Upload only changes files in Path? Have you an Idea?