Upload User Photos to SharePoint Online Library

Upload User Photos to SharePoint Online Library

Simple script to upload user photos to a SharePoint Online library. The photos are pulled from active directory in a separate script.

###
# Upload User Photos to SharePoint Online Library
###
# This script is designed to upload user photos to a SharePoint Online library. It first removes existing photos from the specified library and then uploads new photos from a local directory. The script uses the PnP PowerShell module to interact with SharePoint Online and includes logging and error handling to ensure a smooth execution.
###
# Before running the script, make sure to:
# 1. Install the PnP PowerShell module if you haven't already: Install-Module -Name PnP.PowerShell
# 2. Set up an Azure AD app registration with certificate-based authentication and grant it the necessary permissions to access SharePoint Online.
###
# Note: Be cautious when running scripts that delete content. Always test in a non-production environment first and ensure you have backups if needed.
###
# The script is structured in the following phases:
# 1. Configuration: Set up parameters for sleep intervals, retry logic, and connection settings.
# 2. Connect to SharePoint Online using the specified credentials.
# 3. Remove existing photos from the target library in batches to optimize performance.
# 4. Upload new photos from the local directory, with error handling and logging for each upload.
# 5. Final output of the total number of photos uploaded and completion of the transcript.
###
# Make sure to replace the placeholder values for ClientID, ThumbPrint, Tenant, SiteURL, and DestinationPath with your actual configuration before running the script.
###

Start-Transcript -Path "C:\Temp\UserPhotos\0C - Transscript.txt"

# -----------------------------
# Configuration
# -----------------------------
$DeleteSleepSeconds          = 0    # pause between deletes (0 = no pause)
$BetweenPhasesSleepSeconds   = 15   # pause between delete and upload phases

# -----------------------------
# Connection settings
# -----------------------------
$ClientID   = "00000000-0000-0000-0000-000000000000"  # Replace with your Azure AD app registration's client ID
$ThumbPrint = ""  # Replace with your certificate thumbprint
$Tenant     = "contoso.onmicrosoft.com"  # Replace with your tenant domain

$SiteURL        = "https://contoso.sharepoint.com/sites/YourSite"  # Replace with your SharePoint site URL
$DestinationPath = "Employee Photos"  # Site-relative library/folder path

# Connect to SharePoint Online using Certificate
Connect-PnPOnline -Url $SiteURL -ClientId $ClientID -Thumbprint $ThumbPrint -Tenant $Tenant

# Location of exported photos (files only, excluding scripts and logs)
$newUserPhotos = Get-ChildItem -Path "C:\Temp\UserPhotos\" -Exclude *.txt, *.ps1
$newUserPhotos = $newUserPhotos | Sort-Object
Write-Host "Found $($newUserPhotos.Count) photos on disk"

# -----------------------------
# Remove existing photos
# -----------------------------
try {
    Write-Host ""
    Write-Host "Removing photos from SP"

    $oldUserPhotos = Get-PnPListItem -List $DestinationPath -PageSize 1000
    $totalOld      = $oldUserPhotos.Count
    $oldUserPhotoCount = 0

    if ($totalOld -gt 0) {
        # Batch deletes to reduce round trips
        $batch = New-PnPBatch

        foreach ($oldUserPhoto in $oldUserPhotos) {
            $oldUserPhotoCount++
            Write-Host "Removing old image $oldUserPhotoCount of $totalOld"

            #Remove-PnPListItem -List $DestinationPath -Identity $oldUserPhoto -Batch $batch -Force
            Remove-PnPListItem `
    -List $DestinationPath `
    -Identity $oldUserPhoto.Id `
    -Batch $batch

            if ($DeleteSleepSeconds -gt 0) {
                Start-Sleep -Seconds $DeleteSleepSeconds
            }
        }

        Invoke-PnPBatch -Batch $batch
    }
}
catch {
    Write-Host $_.Exception.Message
    Write-Host "---"
}
finally {
    Write-Host "---"

    if ($BetweenPhasesSleepSeconds -gt 0) {
        Start-Sleep -Seconds $BetweenPhasesSleepSeconds
    }
}

# -----------------------------
# Upload latest photos
# -----------------------------
$totalNew          = $newUserPhotos.Count
$newUserPhotoCount = 0

foreach ($newUserPhoto in $newUserPhotos) {
    $newUserPhotoCount++
    Write-Host "Uploading new image $newUserPhotoCount of $totalNew"

    $newUserPhotoPath     = $newUserPhoto.FullName
    $newUserPhotoFileName = $newUserPhoto.BaseName.Replace('.', ' ') + $newUserPhoto.Extension
    $newUserPhotoTitle    = $newUserPhoto.BaseName.Replace('.', ' ')

    try {
        $uploaded = Add-PnPFile `
            -Path        $newUserPhotoPath `
            -Folder      $DestinationPath `
            -NewFileName $newUserPhotoFileName `
            -Values      @{ "Title" = $newUserPhotoTitle } `
            -Verbose `
            -ErrorAction Stop

        Write-Host "Uploaded $newUserPhotoFileName to $($uploaded.ServerRelativeUrl)"
    }
    catch {
        Write-Host "Upload error for $newUserPhotoPath"
        Write-Host $_.Exception.ToString()
        throw
    }
}

# -----------------------------
# Final output
# -----------------------------
Write-Host ""
Write-Host "---"
Write-Host "Uploaded a total of $($newUserPhotos.Count) photos"
Write-Host "---"

Stop-Transcript

Comments

No comments yet. Why don’t you start the discussion?

Leave a Reply

Your email address will not be published. Required fields are marked *