Monday, 1 July 2019

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, so if you have enough permission on the required user's OneDrive site, then you can do whatever operations (as like you can do with SPO site) in Powershel 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 local folder and upload into an user's OneDrive location.

Permissions Required :

By default every users have full access permission on their personal OneDrive site. If you are going to upload in your own 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 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 root folder. If you specify target folder, then the folder should already exist in 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 not exist in 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 local folder with nested folder structure and upload files and sub folders into the given OneDrive folder with 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 not exist in 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 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 into 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++
}

Advertisements
Advertisements

2 comments:

  1. This doesn't seem to upload subfolders, or any files within subfolders.
    Is there any way this can be achieved?

    ReplyDelete
    Replies
    1. If you want to read files from local folder and sub folders, but upload all files into specified OneDrive directory, then you can just add -Recurse parameter while getting files.

      Replace this line :
      $Files = (Dir $LocalFolder -File)

      With this line :
      $Files = (Dir $LocalFolder -File -Recurse)

      If you want to keep existing folder structure in OneDrive also, then I have added another set of commands for this case, you can refer the above post.

      https://www.morgantechspace.com/2019/07/upload-files-into-onedrive-for-business-using-powershell.html#nestedfolder

      Delete