Uploading bulk files from local system to SharePoint online using PowerShell script throwing an error you cannot call null valued expression - powershell

My requirement is to upload multiple files using PowerShell script to SharePoint online.
while uploading files to a folder in the SharePoint document library, it showing me this error.
I am extracting only file name before uploading and create a folder with that filename and want to upload the file in that particular folder using PowerShell script .
#Load SharePoint CSOM Assemblies
Add-Type -Path "C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\16\ISAPI\Microsoft.SharePoint.Client.dll"
Add-Type -Path "C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\16\ISAPI\Microsoft.SharePoint.Client.Runtime.dll"
### Variables for Processing
$WebUrl = "https://tanviteddu.sharepoint.com/sites/Powershell/"
$LibraryName ="Documents"
$ListURL="/sites/Powershell/Shared Documents/Reports"
$SourceFolder="C:\Hari Priya"
#Setup Credentials to connect
$Credentials = New-Object Microsoft.SharePoint.Client.SharePointOnlineCredentials($UserName,(ConvertTo-SecureString $Password -AsPlainText -Force))
#Set up the context
$Context = New-Object Microsoft.SharePoint.Client.ClientContext($WebUrl)
$Context.Credentials = $Credentials
#Get the Library
$Library = $Context.Web.Lists.GetByTitle($LibraryName)
#upload each file from the directory
Foreach ($File in (dir $SourceFolder -File))
{
$fn=(Split-path -Path $file -Leaf).Split(".")[0];
Try
{
#Set up the context
$Context = New-Object Microsoft.SharePoint.Client.ClientContext($SiteUrl)
$Context.Credentials = $credentials
#Get the List Root Folder
$ParentFolder=$Context.web.GetFolderByServerRelativeUrl($ListURL)
#sharepoint online powershell create folder
$Folder = $ParentFolder.Folders.Add($fn)
$ParentFolder.Context.ExecuteQuery()
Write-host "New Folder Created Successfully!" -ForegroundColor Green
}
catch
{
write-host "Error: $($_.Exception.Message)" -foregroundcolor Red
}
#Get the file from disk
$FileStream = ([System.IO.FileInfo] (Get-Item $File.FullName)).OpenRead()
$FinalUrl=$ListURL+"\"+$fn+"\"+$file
#Upload the File to SharePoint Library
$FileCreationInfo = New-Object
Microsoft.SharePoint.Client.FileCreationInformation
$FileCreationInfo.Overwrite = $true
$FileCreationInfo.ContentStream = $FileStream
$FileCreationInfo.URL = $File
$FileUploaded = $FinalUrl.RootFolder.Files.Add($FileCreationInfo)
#powershell to upload files to sharepoint online
$Context.Load($FileUploaded)
$Context.ExecuteQuery()
#Close file stream
$FileStream.Close()
write-host "File: $($File) has been uploaded!"
}
While uploading, it is showing the error as below:
You cannot call a method on a null-valued expression.
At line:26 char:5
+ $FileUploaded = $FinalUrl.RootFolder.Files.Add($FileCreationInfo)
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (:) [], RuntimeExceptio
+ FullyQualifiedErrorId : InvokeMethodOnNull
Cannot find an overload for "Load" and the argument count: "1".
At line:28 char:5
+ $Context.Load($FileUploaded)
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [], MethodException
+ FullyQualifiedErrorId : MethodCountCouldNotFindBest
Please help me out

The below is working code - upload files from local drive to SharePoint online using PowerShell CSOM:
#Load SharePoint CSOM Assemblies
#Add-Type -Path "C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\16\ISAPI\Microsoft.SharePoint.Client.dll"
#Add-Type -Path "C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\16\ISAPI\Microsoft.SharePoint.Client.Runtime.dll"
cls
$fileName = "File_Uploading_Report"
#'yyyyMMddhhmm yyyyMMdd
$enddate = (Get-Date).tostring("yyyyMMddhhmmss")
#$filename = $enddate + '_VMReport.doc'
$logFileName = $fileName +"_"+ $enddate+"_Log.txt"
$invocation = (Get-Variable MyInvocation).Value
$directoryPath = Split-Path $invocation.MyCommand.Path
$directoryPathForLog=$directoryPath+"\"+"LogFiles"
if(!(Test-Path -path $directoryPathForLog))
{
New-Item -ItemType directory -Path $directoryPathForLog
#Write-Host "Please Provide Proper Log Path" -ForegroundColor Red
}
#$logPath = $directoryPath + "\" + $logFileName
$logPath = $directoryPathForLog + "\" + $logFileName
$isLogFileCreated = $False
#DLL location
$directoryPathForDLL=$directoryPath+"\"+"Dependency Files"
if(!(Test-Path -path $directoryPathForDLL))
{
New-Item -ItemType directory -Path $directoryPathForDLL
#Write-Host "Please Provide Proper Log Path" -ForegroundColor Red
}
#DLL location
$clientDLL=$directoryPathForDLL+"\"+"Microsoft.SharePoint.Client.dll"
$clientDLLRuntime=$directoryPathForDLL+"\"+"Microsoft.SharePoint.Client.dll"
Add-Type -Path $clientDLL
Add-Type -Path $clientDLLRuntime
#Files to upload location
$directoryPathForFileToUploadLocation=$directoryPath+"\"+"Files To Upload"
if(!(Test-Path -path $directoryPathForFileToUploadLocation))
{
New-Item -ItemType directory -Path $directoryPathForFileToUploadLocation
#Write-Host "Please Provide Proper Log Path" -ForegroundColor Red
}
#Files to upload location ends here.
function Write-Log([string]$logMsg)
{
if(!$isLogFileCreated){
Write-Host "Creating Log File..."
if(!(Test-Path -path $directoryPath))
{
Write-Host "Please Provide Proper Log Path" -ForegroundColor Red
}
else
{
$script:isLogFileCreated = $True
Write-Host "Log File ($logFileName) Created..."
[string]$logMessage = [System.String]::Format("[$(Get-Date)] - {0}", $logMsg)
Add-Content -Path $logPath -Value $logMessage
}
}
else
{
[string]$logMessage = [System.String]::Format("[$(Get-Date)] - {0}", $logMsg)
Add-Content -Path $logPath -Value $logMessage
}
}
#The below function will upload the file from local directory to SharePoint Online library.
Function FileUploadToSPOnlineLibrary()
{
param
(
[Parameter(Mandatory=$true)] [string] $SPOSiteURL,
[Parameter(Mandatory=$true)] [string] $SourceFilePath,
[Parameter(Mandatory=$true)] [string] $File,
[Parameter(Mandatory=$true)] [string] $TargetLibrary,
[Parameter(Mandatory=$true)] [string] $UserName,
[Parameter(Mandatory=$true)] [string] $Password
)
Try
{
$securePassword= $Password | ConvertTo-SecureString -AsPlainText -Force
#Setup the Context
$ctx = New-Object Microsoft.SharePoint.Client.ClientContext($SPOSiteURL)
$ctx.Credentials = New-Object Microsoft.SharePoint.Client.SharePointOnlineCredentials($UserName, $securePassword)
$list = $ctx.Web.Lists.GetByTitle($TargetLibrary)
$ctx.Load($list)
$ctx.ExecuteQuery()
$tarGetFilePath=$siteURL+"/"+"$TargetLibrary"+"/"+$File
$fileOpenStream = New-Object IO.FileStream($SourceFilePath, [System.IO.FileMode]::Open)
$fileCreationInfo = New-Object Microsoft.SharePoint.Client.FileCreationInformation
$fileCreationInfo.Overwrite = $true
$fileCreationInfo.ContentStream = $fileOpenStream
$fileCreationInfo.URL = $File
$uploadFileInfo = $list.RootFolder.Files.Add($FileCreationInfo)
$ctx.Load($uploadFileInfo)
$ctx.ExecuteQuery()
Write-host -f Green "File '$SourceFilePath' has been uploaded to '$tarGetFilePath' successfully!"
}
Catch
{
$ErrorMessage = $_.Exception.Message +"in uploading File!: " +$tarGetFilePath
Write-Host $ErrorMessage -BackgroundColor Red
Write-Log $ErrorMessage
}
}
#Variables
$siteURL="https://globalsharepoint.sharepoint.com/sites/TestSite/"
$listName="TestDocumentLibrary"
$fromDate="2019-10-28"
$toDate="2019-11-09"
$filesFolderLoaction=$directoryPathForFileToUploadLocation;
$userName = "YourSPOAccount#YourTenantDomain.com"
$password = "YourPassWord"
$securePassword= $password | ConvertTo-SecureString -AsPlainText -Force
#Variables ends here.
$filesCollectionInSourceDirectory=Get-ChildItem $filesFolderLoaction -File
$uploadItemCount=1;
#Extract the each file item from the folder.
ForEach($oneFile in $filesCollectionInSourceDirectory)
{
try
{
FileUploadToSPOnlineLibrary -SPOSiteURL $siteURL -SourceFilePath $oneFile.FullName -File $oneFile -TargetLibrary $listName -UserName $UserName -Password $Password
$fileUploadingMessage=$uploadItemCount.ToString()+": "+$oneFile.Name;
Write-Host $fileUploadingMessage -BackgroundColor DarkGreen
Write-Log $fileUploadingMessage
$uploadItemCount++
}
catch
{
$ErrorMessage = $_.Exception.Message +"in: " +$oneFile.Name
Write-Host $ErrorMessage -BackgroundColor Red
Write-Log $ErrorMessage
}
}
Write-Host "========================================================================"
Write-Host "Total number of files uploaded: " $filesCollectionInSourceDirectory.Count
Write-Host "========================================================================"
Reference URL:
https://global-sharepoint.com/powershell/upload-files-to-sharepoint-online-document-library-using-powershell-csom/

Related

try catch block inside nested foreach loop

I will upload file under folder onTeams with PowerShell. I am using some try/catch block inside if/else statement. How can we improve my script? Or what do you recommend? I want to know is whether there is any way to make this code run better. I'm new to Powershell, so I don't know what looks like bad code or good code.
Let's say, I've run my script in November 2022. It will create a folder called 2022-10 under "/sites/Team/Shared Documents/General/Documents/2022"
Or I've run my script in February 2023. Firstly, it will create called 2023 mail folder for new year under "/sites/Team/Shared Documents/General/Documents/ Then it will create folder called 2023-01 under "/sites/Team/Shared Documents/General/Documents/2023"
And so on.
My script:
#Config Variables
$SiteURL = "https://company.sharepoint.com/sites/Team"
$SourceFilePath ="C:\Documents\report.csv"
$DestinationFolderPath = "/sites/Team/Shared Documents/General/Documents" #Server Relative URL
Try {
#Connect to PnP Online
Connect-PnPOnline -Url $SiteURL -ClientId "47bf0ca0-1d8a-xxxx-xxx-xxxx" -Tenant 'tenant.onmicrosoft.com' -Thumbprint <Thumbprint>
}
catch {
write-host "Error: $($_.Exception.Message)" -foregroundcolor Red
}
$year= get-date -Format yyyy
$FolderURL = $DestinationFolderPath + "/" + $year
#Try to Get the Folder
$Folder = Get-PnPFolder -Url $FolderURL -ErrorAction SilentlyContinue
#sharepoint online powershell To check if folder exists
If($Folder -ne $null)
{
Write-Host -f Green "Folder exists!"
Try{
$d = (get-date).AddMonths(-1).ToString("yyyy-M")
$FolderPATHLastMonth = $DestinationFolderPath + "/" + $year
Add-PnPFolder -Name $d -Folder $FolderPATHLastMonth
$DestinationFolderPath = $FolderPATHLastMonth + "/" + $d
Add-PnPFile -Path $SourceFilePath -Folder $DestinationFolderPath -ErrorAction Stop
}
catch{
echo $_.Exception
}
}
Else
{
Write-Host -f Yellow "Folder does not exists!"
Try{
Add-PnPFolder -Name $year -Folder $DestinationFolderPath
$d2 = (get-date).AddMonths(-1).ToString("yyyy-M")
$FolderPATHLastMonth = $DestinationFolderPath + "/" + $year
Add-PnPFolder -Name $d2 -Folder $FolderPATHLastMonth
$DestinationFolderPath = $FolderPATHLastMonth + "/" + $d2
Add-PnPFile -Path $SourceFilePath -Folder $DestinationFolderPath -ErrorAction Stop
}
catch{
echo $_.Exception
}
}

How to remove large OneDrive folder or subfolder using PowerShell

I'm planning to delete my OneDrive subfolders using PowerShell but I'm unable to do it because the sub folders is prettry large, have too many depth and items so just wondering how should I modify my script so that I can delete it.
Under the Parent Folder, I used to have 5 Subfolders. I was able to delete the other 3 subfolders already but I wasn't able to do it for the remaining 2 because of the reason above.
Add-Type -Path "C:\Program Files\SharePoint Online Management Shell\Microsoft.Online.SharePoint.PowerShell\Microsoft.SharePoint.Client.dll"
Add-Type -Path "C:\Program Files\SharePoint Online Management Shell\Microsoft.Online.SharePoint.PowerShell\Microsoft.SharePoint.Client.Runtime.dll"
Add-Type -Path "C:\Program Files\SharePoint Online Management Shell\Microsoft.Online.SharePoint.PowerShell\Microsoft.Online.SharePoint.Client.Tenant.dll"
#Key File information for secure connection
$Global:adminUPN = "upn"
$Global:PasswordFile = "C:\scripts\LitHold-OneDrive\key-file\ODpw.txt"
$Global:KeyFile = "C:\scripts\LitHold-OneDrive\key-file\OD.key"
$Global:adminPwd = ""
$CurDate = Get-Date -Format "yyyy-MM-dd"
#Pwd Key Encryption File
$key = Get-Content $Global:KeyFile
$Global:adminPwd = Get-Content $Global:PasswordFile | ConvertTo-SecureString -Key $key
$credential = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList $Global:adminUPN, $Global:adminPwd
#Variables
$SiteURL = "OD URL"
$ServerRelativeUrl= "Documents/parentFolder"
Try {
#Get Credentials to connect
$Credentials = New-Object Microsoft.SharePoint.Client.SharePointOnlineCredentials($Global:adminUPN, $Global:adminPwd)
$ctx = New-Object Microsoft.SharePoint.Client.ClientContext($SiteURL)
$ctx.Credentials = $Credentials
#Get the web from URL
$Web = $Ctx.web
$Ctx.Load($Web)
$Ctx.executeQuery()
#Get the Folder object by Server Relative URL
$Folder = $Web.GetFolderByServerRelativeUrl($ServerRelativeUrl)
$Ctx.Load($Folder)
$Ctx.ExecuteQuery()
#Call the function to empty Folder
Empty-SPOFolder $Folder
#Delete the given Folder itself
Write-host -f Green "Deleting Folder:"$Folder.ServerRelativeUrl
$Folder.Recycle() | Out-Null
$Ctx.ExecuteQuery()
}
Catch {
write-host -f Red "Error:" $_.Exception.Message
}
#Function to Delete all files and Sub-folders of a given Folder
Function Empty-SPOFolder([Microsoft.SharePoint.Client.Folder]$Folder)
{
Try {
#Get All Files from the Folder
$Ctx = $Folder.Context
$Files = $Folder.Files
$Ctx.Load($Files)
$Ctx.ExecuteQuery()
#Iterate through each File in the Root folder
Foreach($File in $Files)
{
#Delete the file
Write-Host -f Green "$File.Name"
$Folder.Files.GetByUrl($File.ServerRelativeUrl).Recycle() | Out-Null
$Folder.Files.GetByUrl($File.ServerRelativeUrl).DeleteObject() | Out-Null
Write-host -f Green "Deleted File '$($File.Name)' from '$($File.ServerRelativeURL)'"
}
$Ctx.ExecuteQuery()
#Process all Sub Folders of the given folder
$SubFolders = $Folder.Folders
$Ctx.Load($SubFolders)
$Ctx.ExecuteQuery()
#delete all subfolders
Foreach($Folder in $SubFolders)
{
#Exclude "Forms" and Hidden folders
#Call the function recursively to empty the folder
Empty-SPOFolder -Folder $Folder
#Delete the folder
Write-Host -f Green "$Folder.UniqueId"
#$Ctx.Web.GetFolderById($Folder.UniqueId).Recycle() | Out-Null
$Ctx.Web.GetFolderById($Folder.UniqueId).DeleteObject() | Out-Null
$Ctx.ExecuteQuery()
Write-host -f Green "Deleted Folder:"$Folder.ServerRelativeUrl
}
}
Catch {
write-host -f Red "Error: $Folder.UniqueId - $File.Name " $_.Exception.Message
}
}

Skip error and exception time-outs in for...each loops Powershell

I'm quite new to PS-scripting. I need to download files and folders from Sharepoint using Powershell. The script I have works fine, but it stops running when there is an error/exception. I already removed the try/catch which makes the script continue running after an error/exception, but it still has long time-outs before downloading the next file. And in fact I would like to keep catching the errors so I can log the names of the files that caused an error in a txt-file or so.
What is the best way to do all of this?
Function Download-SPOFolder()
{
param
(
[Parameter(Mandatory=$true)] [string] $SiteURL,
[Parameter(Mandatory=$true)] [Microsoft.SharePoint.Client.Folder] $SourceFolder,
[Parameter(Mandatory=$true)] [string] $TargetFolder
)
Try {
#Create Local Folder, if it doesn't exist
$FolderName = ($SourceFolder.ServerRelativeURL) -replace "/","\"
$LocalFolder = $TargetFolder + $FolderName
If (!(Test-Path -Path $LocalFolder)) {
New-Item -ItemType Directory -Path $LocalFolder | Out-Null
}
#Get all Files from the folder
$FilesColl = $SourceFolder.Files
$Ctx.Load($FilesColl)
$Ctx.ExecuteQuery()
#Iterate through each file and download
Foreach($File in $FilesColl)
{
$TargetFile = $LocalFolder+"\"+$File.Name
#Download the fileS
$FileInfo = [Microsoft.SharePoint.Client.File]::OpenBinaryDirect($Ctx,$File.ServerRelativeURL)
$WriteStream = [System.IO.File]::Open($TargetFile,[System.IO.FileMode]::Create)
$FileInfo.Stream.CopyTo($WriteStream)
$WriteStream.Close()
write-host -f Green "Downloaded File:"$TargetFile
}
#Process Sub Folders
$SubFolders = $SourceFolder.Folders
$Ctx.Load($SubFolders)
$Ctx.ExecuteQuery()
Foreach($Folder in $SubFolders)
{
If($Folder.Name -ne "Forms")
{
#Call the function recursively
Download-SPOFolder -SiteURL $SiteURL -SourceFolder $Folder -TargetFolder $TargetFolder
}
}
}
Catch {
$msg = $Error[0].Exception.Message
write-host -f Red "Error Downloading Folder! - $msg"
}
}
#Set parameter values
$orgName="myOrgName"
$admin="myUsrName"
$SiteURL="myUrl"
$FolderRelativeUrl="myFolderUrl"
$TargetFolder="C:\Temp"
#Setup Credentials to connect
$cred = Get-Credential -UserName $admin -Message GlobalAdminLogin
Connect-SPOService -Url https://$orgName-admin.sharepoint.com -Credential $cred
$Credentials = New-Object Microsoft.SharePoint.Client.SharePointOnlineCredentials($Cred.Username, $Cred.Password)
#Setup the context
$Ctx = New-Object Microsoft.SharePoint.Client.ClientContext($SiteURL)
$Ctx.Credentials = $Credentials
#Get the Web
$Web = $Ctx.Web
$Ctx.Load($Web)
$Ctx.ExecuteQuery()
$Web.ServerRelativeUrl+$FolderRelativeUrl
#Get the Folder
$SourceFolder = $Web.GetFolderByServerRelativeUrl($Web.ServerRelativeUrl+$FolderRelativeUrl)
$Ctx.Load($SourceFolder)
$Ctx.ExecuteQuery()
#Call the function to download Folder
Download-SPOFolder -SiteURL $SiteURL -SourceFolder $SourceFolder -TargetFolder $TargetFolder

PowerShell script return "The remote server returned an error: (401) Unauthorized"

I want to download all files from Share point and found a useful resource: https://social.technet.microsoft.com/Forums/en-US/7b8a27f9-ae0e-443e-a4a4-8c1cb2ee3429/downloading-files-in-sharepoint-online-powershell?forum=sharepointdevelopment, followed steps
Add-Type -Path "C:\Program Files\Common Files\microsoft shared\Web Server Extensions\16\ISAPI\Microsoft.SharePoint.Client.dll"
Add-Type -Path "C:\Program Files\Common Files\microsoft shared\Web Server Extensions\16\ISAPI\Microsoft.SharePoint.Client.Runtime.dll"
$userName = "myemail#web.com"
$siteCollectionUrl = "https://web.sharepoint.com"
$webUrl = $siteCollectionUrl + "/sites"
$docLibraryTitle = "Application"
$destinationLocalFolder = "C:\test"
#------------------------------------------------
Import-Module C:\SPOMod\SPOMod20160326.psm1
#------------------------------------------------
Connect-SPOCSOM -Username $userName -Url $webUrl
#Download document function
function HTTPDownloadFile ($serverFileLocation, $downloadPath)
{
#create secure password
$sPassword = $password | ConvertTo-SecureString -AsPlainText -Force
$webClient = New-Object System.Net.WebClient
$webClient.Credentials = New-Object Microsoft.SharePoint.Client.SharePointOnlineCredentials($userName, $sPassword)
$webClient.Headers.Add("X-FORMS_BASED_AUTH_ACCEPTED", "f")
[System.Uri]$destinationUri = [System.Uri]$serverFileLocation
Write-Host "Downloading" $serverFileLocation "as" $downloadPath
$webClient.DownloadFile($destinationUri, $DownloadPath)
$webClient.Dispose()
}
#------------------------------------------------
#Get files (not dirs)
$listItems = Get-SPOListItems -ListTitle $docLibraryTitle -IncludeAllProperties $true -Recursive | where {$_.FsObjType -eq 0}
#Iteration on all files in doc. library
foreach ($item in $listItems)
{
[string]$sourceDirectory = $item.FileDirRef
[string]$sourceFileName = $item.FileLeafRef
[String]$sourceFileUrl = $siteCollectionUrl + $item.FileRef
#create destination directory
[string]$destinationDirectory = $destinationLocalFolder + $sourceDirectory
$destinationDirectory = $destinationDirectory.Replace("/","\")
if (!(Test-Path -path $destinationDirectory))
{
New-Item -path $destinationDirectory -type directory
}
#download current version document
[string]$destinationFilePath = $destinationDirectory + "\" + $sourceFileName
HTTPDownloadFile $sourceFileUrl $destinationFilePath
}
Script finds all files but when trying to download :
error:
Exception calling "DownloadFile" with "2" argument(s): "The remote server returned an error: (401) Unauthorized."
At C:\Users\SHAREPOINT.ps1:28 char:5
+ $webClient.DownloadFile($destinationUri, $DownloadPath)
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [], MethodInvocationException
+ FullyQualifiedErrorId : WebException
Please help.
Test script:
Add-Type -Path "C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\16\ISAPI\Microsoft.SharePoint.Client.dll"
Add-Type -Path "C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\16\ISAPI\Microsoft.SharePoint.Client.Runtime.dll"
$userName = "user#xxx.onmicrosoft.com"
$siteCollectionUrl = "https://xxx.sharepoint.com"
$webUrl = $siteCollectionUrl + "/sites/lee"
$docLibraryTitle = "MyDoc4"
$destinationLocalFolder = "C:\test"
#------------------------------------------------
Import-Module C:\Lee\Script\SPOMod\SPOMod20160326.psm1
#------------------------------------------------
Connect-SPOCSOM -Username $userName -Url $webUrl
#Download document function
function HTTPDownloadFile ($serverFileLocation, $downloadPath)
{
#create secure password
#$sPassword=$global:Password
$webClient = New-Object System.Net.WebClient
$webClient.Credentials = $global:ctx.Credentials
$webClient.Headers.Add("X-FORMS_BASED_AUTH_ACCEPTED", "f")
#$webClient.Headers.Add("User-Agent: Other");
[System.Uri]$destinationUri = [System.Uri]$serverFileLocation
Write-Host "Downloading" $serverFileLocation "as" $downloadPath
$webClient.DownloadFile($destinationUri, $DownloadPath)
$webClient.Dispose()
}
#------------------------------------------------
#Get files (not dirs)
$listItems = Get-SPOListItems -ListTitle $docLibraryTitle -IncludeAllProperties $true -Recursive | where {$_.FsObjType -eq 0}
#Iteration on all files in doc. library
foreach ($item in $listItems)
{
[string]$sourceDirectory = $item.FileDirRef
[string]$sourceFileName = $item.FileLeafRef
[String]$sourceFileUrl = $siteCollectionUrl + $item.FileRef
#create destination directory
[string]$destinationDirectory = $destinationLocalFolder + $sourceDirectory
$destinationDirectory = $destinationDirectory.Replace("/","\")
if (!(Test-Path -path $destinationDirectory))
{
New-Item -path $destinationDirectory -type directory
}
#download current version document
[string]$destinationFilePath = $destinationDirectory + "\" + $sourceFileName
HTTPDownloadFile $sourceFileUrl $destinationFilePath
}

Files Upload to wrong folder on Sharepoint Online

I've been attempting to upload files and folders to SharePoint Online using PowerShell. I'm almost there but there is something wrong with the code in the recursive method. It's upload the files into the folder below its supposed to. For example if I had a folder structure and each folder had 3 files:
Folder1\Folder2\Folder3
The files in Folder2 and Folder3 would upload to folder 3.
I know that the folders are getting uploaded first so the path of $UploadSubFolder is updated to the lower folder but I don't know how to fix it! Could you write a bit of code so that the files are uploaded first perhaps?
Can anyone help me with this problem ? Thanks!
Function ImportFiles()
{
ForEach($File in Get-ChildItem $CurrentFolder)
{
If($File.PSIsContainer -eq $false)
{
#Upload File to Folder in Sharepoint
$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 = $UploadSubFolder.Files.Add($FileCreationInfo)
$Context.Load($Upload)
$Context.ExecuteQuery()
}
ElseIf($File.PSIsContainer -eq $True)
{
#Upload SubFolder
$CurrentFolder = $CurrentFolder + "\" + $File.Name
$NewFolder1 = Split-Path $File -leaf
$UploadSubFolder = $UploadSubFolder.Folders.Add($NewFolder1)
$Context.Load($UploadSubFolder)
$Context.ExecuteQuery()
ImportFiles
}
Else
{
Write-Host "Upload Complete"
}
}
}
#Get name of Root folder
$NewFolder = Split-Path $Folder -Leaf
#upload Root folder to sharepoint
$UploadFolder = $List.RootFolder.Folders.Add($NewFolder)
$Context.Load($UploadFolder)
$Context.ExecuteQuery()
ForEach($File in (dir $Folder))
{
if($File.PSIsContainer -eq $false)
{
#Upload File to Folder in Sharepoint
$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 = $UploadFolder.Files.Add($FileCreationInfo)
$Context.Load($Upload)
$Context.ExecuteQuery()
}
else
{
$CurrentFolder = $Folder + "\" + $File.Name
#upload folder
$NewFolder = Split-Path $File -leaf
$UploadSubFolder = $UploadFolder.Folders.Add($NewFolder)
$Context.Load($UploadSubFolder)
$Context.ExecuteQuery()
ImportFiles
}
}
The following PS script could be used for uploading files into Document Library in SharePoint Online.
How to upload files into Document Library in SharePoint Online
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
)
$folderUrls = $FolderUrl.Trim().Split("/",[System.StringSplitOptions]::RemoveEmptyEntries)
$folderUrl = $folderUrls[0]
$curFolder = $ParentFolder.Folders.Add($folderUrl)
$Web.Context.Load($curFolder)
$web.Context.ExecuteQuery()
if ($folderUrls.Length -gt 1)
{
$curFolderUrl = [System.String]::Join("/", $folderUrls, 1, $folderUrls.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
[Microsoft.SharePoint.Client.File]::SaveBinaryDirect($Web.Context, $fileUrl, $LocalFile.OpenRead(), $true)
}
finally {
#$fileStream.Close()
}
}
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 $_
}
}
}
Source: Gist
Usage
$Url = "https://contoso.sharepoint.com"
$UserName = "username#contoso.onmicrosoft.com"
$Password = "password"
$TargetListTitle = "Documents" #Target Library
$SourceFolderPath = "C:\Users\me\Upload" #Source Physical Path
#Upload files
Upload-Files -Url $Url -UserName $UserName -Password $Password -TargetListTitle $TargetListTitle -SourceFolderPath $SourceFolderPath
Key points:
Preserve folder structure