You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

PowerShell 7调用Invoke-RestMethod上传多表单文件失败,PS 5正常

问题

我通过以下PowerShell代码使用REST接口上传文件:

#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

这段代码在PowerShell 5.1中可正常运行,但在PowerShell 7中执行失败,报错信息为“Offset to Central Directory cannot be held in an Int64”。我已确认自己使用了ReadAllBytes而非ReadAllText,排除了相关帖子提到的问题,想了解PowerShell版本间的哪些变化导致了这个问题?

原因与解决方案

核心原因:PowerShell 7的编码与请求处理逻辑变化

  • 字符串转字节流的默认编码改变:PowerShell 5.1中,将二进制字节通过ISO-8859-1转成字符串后,作为Body传递时底层会按原编码转回字节流,不会丢失数据。但PowerShell 7基于.NET Core,传递字符串类型的Body时,Invoke-RestMethod会默认用UTF-8重新编码,破坏了ZIP文件的二进制结构,导致解压时出现目录偏移错误。
  • HTTP请求Body的处理逻辑更严格:.NET Core将字符串类型的Body视为纯文本,不再兼容“用字符串模拟二进制流”的做法,而PowerShell 5.1的底层实现对这种场景兼容性更强。

修正方案

方案1:直接构造字节数组作为请求Body

跳过字符串转换步骤,直接拼接表单头部、文件字节和表单尾部的字节数组,确保二进制数据完整:

# 文件路径
$PathToFile = "C:\Path to file here.zip"
$PackageName = Split-Path $PathToFile -Leaf

# 生成表单边界
$Boundary = (New-Guid).ToString()

# 构造表单头部和尾部的字节流(HTTP头用UTF-8编码)
$headerBytes = [System.Text.Encoding]::UTF8.GetBytes(@"
--$Boundary
Content-Disposition: form-data; name="files"; filename="$PackageName"
Content-Type: application/octet-stream

"@)
$footerBytes = [System.Text.Encoding]::UTF8.GetBytes(@"
--$Boundary--
"@)

# 读取文件原始字节
$fileBytes = [System.IO.File]::ReadAllBytes($PathToFile)

# 合并所有部分的字节数组
$contentBody = $headerBytes + $fileBytes + $footerBytes

# 构造请求参数
$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
}

# 执行上传
Invoke-RestMethod @Parameters

方案2:使用PowerShell 7+内置的-Form参数

这是更简洁可靠的方式,-Form参数会自动处理多部分表单的编码、边界和二进制数据传递,无需手动构造字节流:

$PathToFile = "C:\Path to file here.zip"

$Parameters = @{
    Uri                   = "http://myUrlhere.com/TargetResource"
    Method                = "Post"
    UseDefaultCredentials = $true
    Form                  = @{
        files = Get-Item $PathToFile
    }
}

if ($IsCoreCLR -and ($Parameters.Uri -match '^http:')) {
    $Parameters["AllowUnencryptedAuthentication"] = $true
}

Invoke-RestMethod @Parameters

内容的提问来源于stack exchange,提问作者Tanaka Saito

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.14 09:27:06