Upload files to OneDrive for Business site using PowerShell

OneDrive for Business site (ODFB) is built on top of SharePoint Online (SPO). Users’ personal OneDrive site is nothing but a special site collection in SharePoint. If you have enough permission on the required user’s OneDrive site, you can do whatever operations (as like you can do with SPO site) in Powershell with the help of CSOM and SharePoint Online module. In this post, I am going to share CSOM based Powershell script to fetch documents from the local folder and upload it into a user’s OneDrive location.

Permissions Required:

By default, every user has full access permission on their personal OneDrive site. If you are going to upload it in your drive, then you don’t need extra permission. If you are going to upload files into another user’s OneDrive, then you should add yourself as a site collection admin of the particular user’s OneDrive site. Refer this post for more details: Add Site Collection Admin to OneDrive Users

Required details to upload files into OneDrive document library:

Before proceed you need to replace the following input parameters in the below script.

$LocalFolder – Specify your local folder path.
$AdminAccount – Provide admin user account.
$AdminPass – Provide admin password.
$OneDriveURL – User’s OneDrive site URL.
$TargetFolderName – OneDrive folder where you want to upload. Leave empty if you want to upload in the root folder. If you specify the target folder, then the folder should already exist in the OneDrive root folder.

Available Scripts

Upload local files into OneDrive folder

#Add required references to SharePoint client assembly to use CSOM 
[System.Reflection.Assembly]::LoadWithPartialName("Microsoft.SharePoint.Client")
[System.Reflection.Assembly]::LoadWithPartialName("Microsoft.SharePoint.Client.Runtime")  

#Specify local folder path
$LocalFolder = "C:\Users\UserName\Documents\MyFiles"

#Specify the User account for an Office 365 global admin in your organization
$AdminAccount = "admin@<your tenant name>.onmicrosoft.com"
$AdminPass = "admin_password"

#Specify User's OneDrive Site URL and Folder name
$OneDriveURL = "https://<your tenant name>-my.sharepoint.com/personal/username_domainame_com"
$DocumentLibrary ="Documents"
$TargetFolderName ='' #Leave empty to target root folder

#Connect and Load OneDrive Library and Root Folder
$SecPwd = $(ConvertTo-SecureString $AdminPass -asplaintext -force) 
$Ctx = New-Object Microsoft.SharePoint.Client.ClientContext($OneDriveURL) 
$Credentials = New-Object Microsoft.SharePoint.Client.SharePointOnlineCredentials($AdminAccount,$SecPwd) 
$Ctx.credentials = $Credentials
$List = $Ctx.Web.Lists.GetByTitle("$DocumentLibrary")
$Ctx.Load($List)
$Ctx.Load($List.RootFolder)
$Ctx.ExecuteQuery()

#Setting Target Folder
$TargetFolder = $null;
If($TargetFolderName) {
$TargetFolderRelativeUrl = $List.RootFolder.ServerRelativeUrl+"/"+$TargetFolderName
$TargetFolder = $Ctx.Web.GetFolderByServerRelativeUrl($TargetFolderRelativeUrl)
$Ctx.Load($TargetFolder)
$Ctx.ExecuteQuery()
if(!$TargetFolder.Exists){
Throw  "$TargetFolderName - the target folder does not exist in the OneDrive root folder."
}
} Else {
$TargetFolder = $List.RootFolder
}

#Get files from local folder and Upload into OneDrive folder
$i = 1
$Files = (Dir $LocalFolder -File) # Read files only from root folder
#$Files = (Dir $LocalFolder -File -Recurse) # Read files both from root folder and all sub folders
$TotoalFiles = $Files.Length
ForEach ($File in $Files)
{
Try {
Write-Progress -activity "Uplading $File" -status "$i out of $TotoalFiles completed"
$FileStream = New-Object IO.FileStream($File.FullName,[System.IO.FileMode]::Open)
$FileCreationInfo = New-Object Microsoft.SharePoint.Client.FileCreationInformation
$FileCreationInfo.Overwrite = $true
$FileCreationInfo.ContentStream = $FileStream
$FileCreationInfo.URL = $File
$Upload = $TargetFolder.Files.Add($FileCreationInfo)
$Ctx.Load($Upload)
$Ctx.ExecuteQuery()
}
catch
{
Write-Host $_.Exception.Message -Forground "Red"
}
$i++
}

Upload files recursively from local folder and subfolders with folder structure

You can use the following script to read files recursively from a local folder with a nested folder structure and upload files and subfolders into the given OneDrive folder with a complete folder hierarchy.

#Add required references to SharePoint client assembly to use CSOM 
[System.Reflection.Assembly]::LoadWithPartialName("Microsoft.SharePoint.Client")
[System.Reflection.Assembly]::LoadWithPartialName("Microsoft.SharePoint.Client.Runtime")  

# Specify local folder path
$LocalFolder = "C:\Users\Username\Documents\MyFiles"

# Specify the User account for an Office 365 global admin in your organization
$AdminAccount = "admin@<your tenant name>.onmicrosoft.com"
$AdminPass = "admin_password"

# Specify User's OneDrive Site URL and Folder name
$OneDriveURL = "https://<your tenant name>-my.sharepoint.com/personal/username_domainame_com"
$DocumentLibrary ="Documents"
$TargetFolderName ='' #Leave empty to target root folder

#Connect and Load OneDrive Library and Root Folder
$SecPwd = $(ConvertTo-SecureString $AdminPass -asplaintext -force) 
$Ctx = New-Object Microsoft.SharePoint.Client.ClientContext($OneDriveURL) 
$Credentials = New-Object Microsoft.SharePoint.Client.SharePointOnlineCredentials($AdminAccount,$SecPwd) 
$Ctx.credentials = $Credentials
$List = $Ctx.Web.Lists.GetByTitle($DocumentLibrary)
$Ctx.Load($List)
$Ctx.Load($List.RootFolder)
$Ctx.ExecuteQuery()

# Setting Target Folder
$TargetFolder = $null;
$TargetFolderRelativeUrl;
If($TargetFolderName) {
$TargetFolderRelativeUrl = $List.RootFolder.ServerRelativeUrl+"/"+$TargetFolderName
$TargetFolder = $Ctx.Web.GetFolderByServerRelativeUrl($TargetFolderRelativeUrl)
$Ctx.Load($TargetFolder)
$Ctx.ExecuteQuery()
if(!$TargetFolder.Exists){
Throw  "$TargetFolderName - the target folder does not exist in the OneDrive root folder."
}
} Else {
$TargetFolder = $List.RootFolder
$TargetFolderRelativeUrl = $TargetFolder.ServerRelativeUrl
}

# Get folders and sub folders from source location
$folders= @()
foreach ($file in (Get-ChildItem  -Recurse -Path $LocalFolder -Attributes Directory))
{
$folders +=($file.FullName).replace($LocalFolder+"\",'')
}
 
# Create folders and sub-folders in the destination location
Write-Progress -activity "Creating folder structure in OneDrive" -status "Creating Folder"
foreach ($folder in $folders)
{
$subfolder_names = $folder.split("\")
$subfolder = $TargetFolder.Folders.Add($subfolder_names[0])
$Ctx.Load($subfolder)
$Ctx.ExecuteQuery()
for ($i = 1; $i -le ($subfolder_names.Count-1) ; $i++)
{
$subfolder = $subfolder.folders.Add($subfolder_names[$i])
$Ctx.Load($subfolder)
$Ctx.ExecuteQuery()
}
}

# Read all files recursively from the local folder and upload them into the corresponding OneDrive folder.
$i = 1
$Files = (Dir $LocalFolder -File -Recurse)
$TotoalFiles = $Files.Length
ForEach($File in $Files)
{
Try {
$URL_Dest = $TargetFolderRelativeUrl +(($file.FullName).Replace($LocalFolder,'')).Replace("\","/")
Write-Progress -activity "Uplading $File" -status "$i out of $TotoalFiles completed"
$FileStream = New-Object IO.FileStream($File.FullName,[System.IO.FileMode]::Open)
$FileCreationInfo = New-Object Microsoft.SharePoint.Client.FileCreationInformation
$FileCreationInfo.Overwrite = $true
$FileCreationInfo.ContentStream = $FileStream
$FileCreationInfo.URL = $URL_Dest
$Upload = $TargetFolder.Files.Add($FileCreationInfo)
$Ctx.Load($Upload)
$Ctx.ExecuteQuery()
}
catch {
Write-Host $_.Exception.Message -Forground "Red"
}
$i++
}
Advertisement

21 thoughts on “Upload files to OneDrive for Business site using PowerShell”

  1. hi morgan, please can you help with my above queries, i see alot of object reference errors when using the above

    Reply
  2. Works great, but I keep getting an error if I try to specify a target folder. I’ve ensured that the folder exists in the OneDrive root directory. Any thoughts?

    Reports – the target folder does not exist in the OneDrive root folder.
    At line:36 char:1
    + Throw “$TargetFolderName – the target folder does not exist in the OneDrive roo …
    + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo : OperationStopped: (Reports – the t…ve root folder.:String) [], RuntimeException
    + FullyQualifiedErrorId : Reports – the target folder does not exist in the OneDrive root folder.

    Reply
  3. New-Object : Cannot find type [Microsoft.SharePoint.Client.ClientContext]: verify that the assembly containing this type is loaded.
    At C:\Users\admin\Desktop\new_file_powershell.ps1:20 char:8
    + $Ctx = New-Object Microsoft.SharePoint.Client.ClientContext($OneDrive …
    + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo : InvalidType: (:) [New-Object], PSArgumentException
    + FullyQualifiedErrorId : TypeNotFound,Microsoft.PowerShell.Commands.NewObjectCommand

    You cannot call a method on a null-valued expression.
    At C:\Users\admin\Desktop\new_file_powershell.ps1:24 char:1
    + $Ctx.Load($List)
    + ~~~~~~~~~~~~~~~~
    + CategoryInfo : InvalidOperation: (:) [], RuntimeException
    + FullyQualifiedErrorId : InvokeMethodOnNull

    Reply
    • Can you confirm the following commands loads the required assemblies.?

      #Load required SharePoint client assemblies
      [System.Reflection.Assembly]::LoadWithPartialName(“Microsoft.SharePoint.Client”)
      [System.Reflection.Assembly]::LoadWithPartialName(“Microsoft.SharePoint.Client.Runtime”)

      Reply

Leave a Comment