Private/Publish-FolderToSharePoint.ps1
<#
.SYNOPSIS Recursively uploads a local folder and its contents to a SharePoint Online document library using optional secure authentication. .DESCRIPTION The Publish-FolderToSharePoint function uploads all files and subfolders from a specified local directory to a SharePoint Online document library. It supports secure authentication using encrypted passcodes or fallback to interactive login (UseWebLogin). Folder structure is preserved on SharePoint, and folders are created dynamically if missing. .PARAMETER LocalFolderPath Specifies the full path of the local folder whose contents are to be uploaded. .PARAMETER SharePointSiteUrl The URL of the SharePoint Online site to which files will be uploaded. .PARAMETER SharePointFolderRelativeUrl The server-relative URL of the SharePoint folder where content should be placed (e.g., "Shared Documents/Reports"). .PARAMETER Username The SharePoint or Microsoft 365 account username used for secure authentication. If omitted, interactive login will be used. .PARAMETER Passcode Encrypted passcode string that is decrypted using the username to derive the password. Used only if Username is provided. .EXAMPLE Publish-FolderToSharePoint ` -LocalFolderPath "C:\Reports\Citrix" ` -SharePointSiteUrl "https://company.sharepoint.com/sites/ITCMR" ` -SharePointFolderRelativeUrl "Shared Documents/Reports/Citrix" .EXAMPLE Publish-FolderToSharePoint ` -LocalFolderPath "C:\Exports" ` -SharePointSiteUrl "https://company.sharepoint.com/sites/Finance" ` -SharePointFolderRelativeUrl "Documents/FY24" ` -Username "service.sharepoint@company.com" ` -Passcode "Base64EncryptedPass123..." .NOTES - Requires the PnP PowerShell module (Install-Module PnP.PowerShell). - Uses Write-LogEntry for logging actions and status. - Handles recursive file and folder upload with SharePoint folder checks. #> function Publish-FolderToSharePoint { [CmdletBinding()] param ( [Parameter(Mandatory = $true)] [string]$LocalFolderPath, [Parameter(Mandatory = $true)] [string]$SharePointSiteUrl, [Parameter(Mandatory = $true)] [string]$SharePointFolderRelativeUrl, [Parameter(Mandatory = $false)] [string]$Username, [Parameter(Mandatory = $false)] [string]$Passcode ) try { if ($PSBoundParameters.ContainsKey("Username") -and $PSBoundParameters.ContainsKey("Passcode")) { $passwordPlain = ConvertFrom-SecurePasscode -Passcode $Passcode -Username $Username $securePassword = ConvertTo-SecureString $passwordPlain -AsPlainText -Force $credential = New-Object System.Management.Automation.PSCredential ($Username, $securePassword) Connect-PnPOnline -Url $SharePointSiteUrl -Credentials $credential } else { Connect-PnPOnline -Url $SharePointSiteUrl -UseWebLogin } function Upload-Recursive { param ( [string]$CurrentPath, [string]$CurrentSPPath ) Get-ChildItem -Path $CurrentPath -File | ForEach-Object { $destination = "$CurrentSPPath/$($_.Name)" Write-LogEntry -Message "⬆ Uploading: $($_.FullName) → $destination" Add-PnPFile -Path $_.FullName -Folder $CurrentSPPath -ErrorAction SilentlyContinue } Get-ChildItem -Path $CurrentPath -Directory | ForEach-Object { $subSPPath = "$CurrentSPPath/$($_.Name)" if (-not (Get-PnPFolder -Url $subSPPath -ErrorAction SilentlyContinue)) { Write-LogEntry -Message "📁 Creating SharePoint folder: $subSPPath" Add-PnPFolder -Name $_.Name -Folder $CurrentSPPath } Upload-Recursive -CurrentPath $_.FullName -CurrentSPPath $subSPPath } } Upload-Recursive -CurrentPath $LocalFolderPath -CurrentSPPath $SharePointFolderRelativeUrl } catch { Write-LogEntry -Message "❌ Upload failed: $_" } finally { Disconnect-PnPOnline } } |