Montag, 15. April 2019

Rekursives Hochladen von Ordnern in SharePoint mit PNP

Die Frage heute beim Kunden war: Kann ich "schnell" und mit PNP (d.h. ohne server-code) einen kompletten Ordner - mit Unterordnern - in eine SharePoint-Bibliothek hochladen?

Die Antwort ist ja, aber... (nicht "einfach so")
Ich habe hier ein Skript vorbereitet, dass die Arbeit übernimmt:

  • Erstellen eines Ordners im SharePoint, falls gewünscht
  • Hochladen aller Dateien aus dem Quell-Ordner
  • Rekursive Verarbeitung aller Unterverzeichnisse
<#  
.SYNOPSIS  
    Uploads a Folder, including all Files and subfolders
.Notes
    This Cmdlet assumes you have PNP installed and Connect-PNPOnline was issued before this command.
.Example
    Add-PNPFolderRecursive -Path C:\temp -Folder /SiteAssets -NoRootFolderCreation
    Uploads all of c:\temp to /SiteAssets
.Example
    Add-PNPFolderRecursive -Path C:\temp -Folder /SiteAssets
    Creates a "temp" folder in /SiteAssets, then uploads all of c:\temp to the newly created /SiteAssets/temp
#>
[CmdletBinding()]
param(
    [Parameter(Position=0, 
        Mandatory=$true)]
    $Path,
    [Parameter(Position=1, 
        Mandatory=$true)]
    $Folder,
    [Parameter(Mandatory=$false)]
    [switch]$NoRootFolderCreation
)
$ErrorActionPreference="Stop"

$dstFolder = Get-PNPFolder $Folder
Write-Verbose "Acquired folder: $($dstFolder.ServerRelativeUrl)"

if(!$NoRootFolderCreation.IsPresent) {
    $folderName = Split-Path -Leaf $Path
    Write-Verbose "Creating target-folder $folderName"
    Add-PNPFolder -Name $folderName -Folder $dstFolder.ServerRelativeUrl
    $dstFolder = Get-PNPFolder "$($dstFolder.ServerRelativeUrl)/$($folderName)"
    Write-Verbose "Acquired folder: $($dstFolder.ServerRelativeUrl)"
}

# get all childs of "path" and upload the files...
$files = Get-ChildItem -File -Path $Path

$files | % {
    Write-Verbose "Uploading $($_.FullName)"
    Add-PNPFile -Path $_.FullName -Folder $dstFolder.ServerRelativeUrl | Out-Null
}

# recursive call subfolders
$foders = Get-ChildItem -Directory -Path $Path

$foders | %{
    Write-Verbose "Descending to Folder: $($_.FullName)"
    Invoke-Expression -Command ($PSCommandPath + " -Path $($_.FullName) -Folder $($dstFolder.ServerRelativeUrl) ")
}
Write-verbose "Done for $Path"

Achtung: Ich bin nicht sicher, wie sich das Skript verhält, wenn sehr viele und tiefe Ordnerstrukturen vorliegen - aufgrund der Rekursion im Skript selber vermute ich, dass die Performance ab einem bestimmten Punkt deutlich einbrechen wird.