I am uploading files to a resource using REST in the following way.
#File names
$PathToFile = "C:\Path to file here.zip"
$PackageName = $(Split-Path $PathToFile -Leaf)
#Byte stream and encoding
$PackageByteStream = [System.IO.File]::ReadAllBytes("$PathToFile")
$Encoding = [System.Text.Encoding]::GetEncoding("ISO-8859-1")
$FileEncoding = $Encoding.GetString($PackageByteStream)
#Create the content body
$Boundary = (New-Guid).ToString()
$ContentBody = "--$Boundary
Content-Disposition: form-data; name=""files""; filename=""$PackageName""
Content-Type: application/octet-stream
$FileEncoding
--$Boundary--
"
#Parameter Object
$Parameters = @{
Uri = "http://myUrlhere.com/TargetResource"
Method = "Post"
UseDefaultCredentials = $true
ContentType = "multipart/form-data; boundary=`"$Boundary`""
Body = $ContentBody
}
if ($IsCoreCLR -and ($Parameters.Uri -match '^http:')) {
$Parameters += @{ "AllowUnencryptedAuthentication" = $true }
}
#Upload the file
Invoke-RestMethod @Parameters
This works in Powershell 5.1 but in Powershell 7 it fails with "Offset to Central Directory cannot be held in an Int64". The only related post I could find on that was someone who used ReadAllText instead of ReadAllBytes, but since I already use ReadAllBytes I don't think it's that.
Is there something that has changed between Powershell versions that would cause this behaviour?
I presume you've run into the following:
In PowerShell (Core) 7 v7.4+, the web cmdlets (Invoke-WebRequest
, Invoke-RestMethod
) consistently encode text-based request bodies as UTF-8, unless explicitly specified otherwise.
Previously, and still in Windows PowerShell, the default was ISO-8859-1, except for JSON, which has been UTF-8-encoded since v7.0.
To use ISO-8859-1 encoding in v7.4+, append ; charset=iso-8859-1
to the
-ContentType
value (or, via -Headers
, to the Content-Type
field).
In other words, in the context of your splatted arguments:
# ...
$Parameters = @{
Uri = "http://myUrlhere.com/TargetResource"
Method = "Post"
UseDefaultCredentials = $true
ContentType = "multipart/form-data; boundary=`"$Boundary`"; charset=iso-8859-1"
Body = $ContentBody
}
# ...
Invoke-RestMethod @Parameters
Taking a step back:
In PowerShell 7, instead of manually constructing your multipart/form-data
request body as text, consider using a streamlined approach based on a hashtable passed to the -Form
parameter that references the file to upload via a Get-Item
call: see example 6 of the Invoke-WebRequest
help topic.
If you need more control over the submission, use the lower-level technique shown in example 5.
Note: These techniques should equally work with the Invoke-RestMethod
cmdlet; Invoke-RestMethod
and Invoke-WebRequest
support the same parameters and differ only in the data type of their return value, reflecting their respective focus: Invoke-WebRequest
is focused on HTML-page retrieval, whereas Invoke-RestMethod
is focused on calling HTTP-based APIs (not only REST-ful ones); see this answer for more information.