NEC SV9100 Bulk Photo Upload

On our new SV9100 system we needed a way to bulk upload user thumbnails for their extensions to appear on the new colour screen ITK phones. NEC does not appears to have any way to do this so I have written the following script.

It requires a folder containing your images with the filename ending in the extension it should be uploaded to. This works best if you pre-crop your images to square or similar as on phone the image will be cropped.

Bulk upload extension photos to SV9100
Script to upload photos based on extension number to NEC SV9100 PABX, or perform other bulk individual operations
Photo can be checked at "http://<IP>/UserImages/000.jpg" where number is port – 1
Image names must have extension as last part of name e.g. "Name 122.jpg"
Update stored directory of photos below
Enter the password for a User1 level user.
Author: James Rudd
Blog :
# Folder where images are stored. Image names must have extension as last part of name e.g. "Name 342.jpg"
$TARGET_FOLDER_PATH = "C:\Temp\Pics\2020"
$pabxHost="<PABX IP>"
$pabxBase = "http://$pabxHost" # Allows HTTPS if configured
# Configure Variables
$necSep = [char]18 # NEC Item seperator
$LF = "`r`n"
# Needed to resize images for PABX
Function ResizeImage() {
param([String]$ImagePath, [Int]$Quality = 90, [Int]$targetSize, [String]$OutputLocation)
Add-Type AssemblyName "System.Drawing"
$img = [System.Drawing.Image]::FromFile($ImagePath)
$CanvasWidth = $targetSize
$CanvasHeight = $targetSize
#Encoder parameter for image quality
$ImageEncoder = [System.Drawing.Imaging.Encoder]::Quality
$encoderParams = New-Object System.Drawing.Imaging.EncoderParameters(1)
$encoderParams.Param[0] = New-Object System.Drawing.Imaging.EncoderParameter($ImageEncoder, $Quality)
# get codec
$Codec = [System.Drawing.Imaging.ImageCodecInfo]::GetImageEncoders() | Where-Object {$_.MimeType -eq 'image/jpeg'}
#compute the final ratio to use
$ratioX = $CanvasWidth / $img.Width;
$ratioY = $CanvasHeight / $img.Height;
$ratio = $ratioY
if ($ratioX -le $ratioY) {
$ratio = $ratioX
$newWidth = [int] ($img.Width * $ratio)
$newHeight = [int] ($img.Height * $ratio)
$bmpResized = New-Object System.Drawing.Bitmap($newWidth, $newHeight)
$graph = [System.Drawing.Graphics]::FromImage($bmpResized)
$graph.InterpolationMode = [System.Drawing.Drawing2D.InterpolationMode]::HighQualityBicubic
$graph.DrawImage($img, 0, 0, $newWidth, $newHeight)
#save to file
$bmpResized.Save($OutputLocation, $Codec, $($encoderParams))
# Get Session ID
$R = Invoke-WebRequest "${pabxBase}/Login.htm" SessionVariable necLogin Method POST
# Login.htm?sessionId=&LOGIN()
$UrlLogin = "${pabxBase}/Login.htm%3FsessionId%3D%26LOGIN%28%29"
$Body = @{
formData = "0${necSep}userName=$pabxUser${necSep}language=onChange=${necSep}password=$pabxPass"
$R = Invoke-WebRequest Uri $UrlLogin WebSession $necLogin Method POST Body $Body
$extPort = @{}
foreach ($script in $R.Scripts) {
# Get Session ID
if ($script.innerHTML -match 'g_sessionId="(\S+)";'){
#Generate extension to port mappings
if ($script.src -like "*.jsx"){
$URL = "${pabxBase}/" + $script.src
$extList = (Invoke-WebRequest $URL WebSession $necLogin).Content.Split(";")
foreach ($ext in $extList) {
if ( $ext -match 'tel\((\d+),"(\d+)","(\w+)"\)'){
$extPort.Add($Matches[2],@($Matches[1],$Matches[3])) # Ext = (Port, Type [ve|tel])
if (($sessionID -eq "") -or ($extPort.Count -lt 5 )){
#Failed to login and download extensions
Write-Host "Could not login or download extensions list" ForegroundColor Red
# Go through folder and upload images to extension of filename
$ThumbJpgDir = "$TARGET_FOLDER_PATH\thumb"
New-Item ItemType Directory Force Path $ThumbJpgDir
#for($port=0;$port -lt 2; $port++) {
Get-ChildItem $TARGET_FOLDER_PATH Filter *.jpg |
Foreach-Object {
$fileName = $_.Name
# Check file name contains extension
if ($fileName -match '(\d+).[jJ][pP][gG]' ){
else {
Write-Host "Could not match $fileName" ForegroundColor Red
# Check NEC system has a matching Extension
if ($extPort.ContainsKey($ext)){
$portNum=[int]$extPort[$ext][0] + 1
} else {
Write-Host "Could not find $ext on NEC System" ForegroundColor Red
$filePath = "$ThumbJpgDir\$fileName"
# Image must have longest edge as 160 pixel
# Max file size is 15*1024 bytes = 15kB
ResizeImage $LDA_TARGET_FILE_NAME 90 160 $filePath
# Load Initial Page.
# Best not to load as can lock phone. Not needed for upload
$URLassemb = "?sessionId=${sessionID}&FEAT_TEL%2823,0,${portNum}%29"
#$URL = "${pabxBase}/UserPro.htm" + [uri]::EscapeDataString($URLassemb)
$URL = "${pabxBase}/UserPro.htm" + $URLassemb
# Not sure if I need to load page
$WebResponse = Invoke-WebRequest $URL -WebSession $necLogin
Write-Verbose $URL
# Post Image
$URLassemb = "?sessionId=${sessionID}&UPLOAD_USER_IMG()"
$URLPost = "${pabxBase}/UserPro.htm" + $URLassemb
# From
$boundary = [System.Guid]::NewGuid().ToString()
$boundary = "—-WebKitFormBoundary" + $boundary.Replace("","").SubString(0,16)
# Headers
$headers = New-Object "System.Collections.Generic.Dictionary[[String],[String]]"
$headers.Add("Accept", "*/*")
$headers.Add("Referer", $URL)
$headers.Add("Origin", "${pabxBase}")
$headers.Add("Accept-Encoding", "gzip, deflate")
$headers.Add("Accept-Language", "en-AU,en-GB;q=0.9,en-US;q=0.8,en;q=0.7")
$headers.Add("dnt", "1")
# Read in Image
$fileRead = [System.IO.File]::ReadAllBytes($FilePath)
$fileEnc = [System.Text.Encoding]::GetEncoding("iso-8859-1").GetString($fileRead)
# Generate the multipart message
$bodyLines = (
"Content-Disposition: form-data; name=`"portNo`"$LF",
"Content-Disposition: form-data; name=`"fileName`"$LF",
"Content-Disposition: form-data; name=`"userImagePath`"; filename=`"newImg.jpg`"",
"Content-Type: image/jpeg$LF",
) -join $LF
$Attach = Invoke-RestMethod Uri $URLPost Headers $headers Method Post ContentType "multipart/form-data; boundary=$boundary" TimeoutSec 20 Body $bodyLines
Write-host "Uploaded extension $ext to port $portNum"
# Need to logoff to clear connections
$URL = "${pabxBase}/Home.htm?sessionId=$sessionID&LOGOUT%28%29"
Invoke-WebRequest Uri $URL WebSession $necLogin |Out-Null
view raw Update-NECPhotos.ps1 hosted with ❤ by GitHub
No tag for this post.

About James Rudd

Network Administrator at Sydney Boys High School
This entry was posted in General, PABX. Bookmark the permalink.

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.