如何使用PowerShell Invoke-RestMethod发送multipart / form-data

时间:2022-03-09 00:39:30

I'm trying to send a file via Invoke-RestMethod in a similar context as curl with the -F switch.

我正在尝试通过Invoke-RestMethod在类似的上下文中使用-F开关发送文件。

Curl Example

卷曲示例

curl -F FileName=@"/path-to-file.name" "https://uri-to-post"

In powershell, I've tried something like this:

在powershell中,我尝试过这样的事情:

$uri = "https://uri-to-post"
$contentType = "multipart/form-data"
$body = @{
    "FileName" = Get-Content($filePath) -Raw
}

Invoke-WebRequest -Uri $uri -Method Post -ContentType $contentType -Body $body
}

If I check fiddler I see that the body contains the raw binary data, but I get a 200 response back showing no payload has been sent.

如果我检查fiddler,我看到正文包含原始二进制数据,但我得到200响应,显示没有发送有效负载。

I've also tried to use the -InFile parameter with no luck.

我也尝试过使用-InFile参数而没有运气。

I've seen a number of examples using a .net class, but was trying to keep this simple with the newer Powershell 3 commands.

我已经看过许多使用.net类的例子,但是他们试图用更新的Powershell 3命令来保持这个简单。

Does anyone have any guidance or experience making this work?

有没有人有任何指导或经验使这项工作?

3 个解决方案

#1


10  

The problem here was what the API required some additional parameters. Initial request required some parameters to accept raw content and specify filename/size. After setting that and getting back proper link to submit, I was able to use:

这里的问题是API需要一些额外的参数。初始请求需要一些参数来接受原始内容并指定文件名/大小。在设置并返回正确的提交链接后,我能够使用:

Invoke-RestMethod -Uri $uri -Method Post -InFile $filePath -ContentType "multipart/form-data"

#2


4  

The accepted answer won't do a multipart/form-data request, but rather a application/x-www-form-urlencoded request forcing the Content-Type header to a value that the body does not contain.

接受的答案不会执行multipart / form-data请求,而是应用/ x-www-form-urlencoded请求将Content-Type标头强制为正文不包含的值。

One way to send a multipart/form-data formatted request with PowerShell is:

使用PowerShell发送multipart / form-data格式化请求的一种方法是:

$ErrorActionPreference = 'Stop'

$fieldName = 'file'
$filePath = 'C:\Temp\test.pdf'
$url = 'http://posttestserver.com/post.php'

Try {
    Add-Type -AssemblyName 'System.Net.Http'

    $client = New-Object System.Net.Http.HttpClient
    $content = New-Object System.Net.Http.MultipartFormDataContent
    $fileStream = [System.IO.File]::OpenRead($filePath)
    $fileName = [System.IO.Path]::GetFileName($filePath)
    $fileContent = New-Object System.Net.Http.StreamContent($fileStream)
    $content.Add($fileContent, $fieldName, $fileName)

    $result = $client.PostAsync($url, $content).Result
    $result.EnsureSuccessStatusCode()
}
Catch {
    Write-Error $_
    exit 1
}
Finally {
    if ($client -ne $null) { $client.Dispose() }
    if ($content -ne $null) { $content.Dispose() }
    if ($fileStream -ne $null) { $fileStream.Dispose() }
    if ($fileContent -ne $null) { $fileContent.Dispose() }
}

#3


1  

I found this post and changed it a bit

我发现这篇文章并稍微改了一下

$fileName = "..."
$uri = "..."

$currentPath = Convert-Path .
$filePath="$currentPath\$fileName"

$fileBin = [System.IO.File]::ReadAlltext($filePath)
$boundary = [System.Guid]::NewGuid().ToString()
$LF = "`r`n"
$bodyLines = (
    "--$boundary",
    "Content-Disposition: form-data; name=`"file`"; filename=`"$fileName`"",
    "Content-Type: application/octet-stream$LF",
    $fileBin,
    "--$boundary--$LF"
) -join $LF

Invoke-RestMethod -Uri $uri -Method Post -ContentType "multipart/form-data; boundary=`"$boundary`"" -Body $bodyLines

#1


10  

The problem here was what the API required some additional parameters. Initial request required some parameters to accept raw content and specify filename/size. After setting that and getting back proper link to submit, I was able to use:

这里的问题是API需要一些额外的参数。初始请求需要一些参数来接受原始内容并指定文件名/大小。在设置并返回正确的提交链接后,我能够使用:

Invoke-RestMethod -Uri $uri -Method Post -InFile $filePath -ContentType "multipart/form-data"

#2


4  

The accepted answer won't do a multipart/form-data request, but rather a application/x-www-form-urlencoded request forcing the Content-Type header to a value that the body does not contain.

接受的答案不会执行multipart / form-data请求,而是应用/ x-www-form-urlencoded请求将Content-Type标头强制为正文不包含的值。

One way to send a multipart/form-data formatted request with PowerShell is:

使用PowerShell发送multipart / form-data格式化请求的一种方法是:

$ErrorActionPreference = 'Stop'

$fieldName = 'file'
$filePath = 'C:\Temp\test.pdf'
$url = 'http://posttestserver.com/post.php'

Try {
    Add-Type -AssemblyName 'System.Net.Http'

    $client = New-Object System.Net.Http.HttpClient
    $content = New-Object System.Net.Http.MultipartFormDataContent
    $fileStream = [System.IO.File]::OpenRead($filePath)
    $fileName = [System.IO.Path]::GetFileName($filePath)
    $fileContent = New-Object System.Net.Http.StreamContent($fileStream)
    $content.Add($fileContent, $fieldName, $fileName)

    $result = $client.PostAsync($url, $content).Result
    $result.EnsureSuccessStatusCode()
}
Catch {
    Write-Error $_
    exit 1
}
Finally {
    if ($client -ne $null) { $client.Dispose() }
    if ($content -ne $null) { $content.Dispose() }
    if ($fileStream -ne $null) { $fileStream.Dispose() }
    if ($fileContent -ne $null) { $fileContent.Dispose() }
}

#3


1  

I found this post and changed it a bit

我发现这篇文章并稍微改了一下

$fileName = "..."
$uri = "..."

$currentPath = Convert-Path .
$filePath="$currentPath\$fileName"

$fileBin = [System.IO.File]::ReadAlltext($filePath)
$boundary = [System.Guid]::NewGuid().ToString()
$LF = "`r`n"
$bodyLines = (
    "--$boundary",
    "Content-Disposition: form-data; name=`"file`"; filename=`"$fileName`"",
    "Content-Type: application/octet-stream$LF",
    $fileBin,
    "--$boundary--$LF"
) -join $LF

Invoke-RestMethod -Uri $uri -Method Post -ContentType "multipart/form-data; boundary=`"$boundary`"" -Body $bodyLines