Как отправить multipart/form-data с помощью PowerShell Invoke-RestMethod
Я пытаюсь отправить файл через Invoke-RestMethod в том же контексте, что и curl с ключом -F.
Пример скручивания
curl -F [email protected]"/path-to-file.name" "https://uri-to-post"
В 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
}
Если я проверяю скрипач, я вижу, что тело содержит необработанные двоичные данные, но я получаю ответ 200 назад, пока не было отправлено никакой полезной нагрузки.
Я также попытался использовать параметр -InFile без везения.
Я видел несколько примеров, использующих класс .net, но пытался сохранить это с помощью новых команд Powershell 3.
Есть ли у кого-нибудь какие-либо рекомендации или опыт в этой работе?
Ответы
Ответ 1
Проблема заключалась в том, что API требовал дополнительных параметров. Первоначальный запрос требовал некоторых параметров для приема необработанного содержимого и указания имени файла/размера. После установки этого параметра и возврата правильной ссылки для отправки я смог использовать:
Invoke-RestMethod -Uri $uri -Method Post -InFile $filePath -ContentType "multipart/form-data"
Ответ 2
Принятый ответ не будет выполнять запрос multipart/form-data
, а скорее запрос application/x-www-form-urlencoded
, заставляющий заголовок Content-Type
присваивать значение, которое тело не содержит.
Один способ отправить отформатированный запрос multipart/form-data
с помощью PowerShell:
$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
Я нашел этот post и немного изменил его
$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