Create an account

Very important

  • To access the important data of the forums, you must be active in each forum and especially in the leaks and database leaks section, send data and after sending the data and activity, data and important content will be opened and visible for you.
  • You will only see chat messages from people who are at or below your level.
  • More than 500,000 database leaks and millions of account leaks are waiting for you, so access and view with more activity.
  • Many important data are inactive and inaccessible for you, so open them with activity. (This will be done automatically)


Thread Rating:
  • 417 Vote(s) - 3.56 Average
  • 1
  • 2
  • 3
  • 4
  • 5
How to send multipart/form-data with PowerShell Invoke-RestMethod

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

Curl Example

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

In powershell, I've tried something like this:

$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.

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

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

Does anyone have any guidance or experience making this work?
Reply

#2
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:

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

Reply

#3
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.

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

$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() }
}
Reply

#4
I found this [post][1] 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]:

[To see links please register here]

Reply

#5
For anyone wondering (like Jelphy) whether David's answer can be used with cookies/credentials, the answer is yes.

First set the session with Invoke-WebRequest:

Invoke-WebRequest -Uri "$LoginUri" -Method Get -SessionVariable 'Session'

Then POST to the Login URL, which stores the authentication cookie in `$Session`:

$Response = Invoke-WebRequest -Uri "$Uri" -Method Post -Body $Body -WebSession $Session

[The steps above are the standard way to deal with session in Powershell][1]. But here is the important part. Before creating the HttpClient, create an HttpClientHandler and set it's CookieContainer property with the cookies from the session:

$ClientMessageHandler = New-Object System.Net.Http.HttpClientHandler
$ClientMessageHandler.CookieContainer = $Session.Cookies

Then pass this object to the HttpClient constructor

$Client = [System.Net.Http.HttpClient]::new($ClientMessageHandler)

Voila, you now have an HttpClient with session cookies set automatically via Invoke-WebRequest. The rest of David's example should work (copied here for completeness):

$MultipartFormData = 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)
$MultipartFormData.Add($FileContent, $FieldName, $FileName)

$Result = $Client.PostAsync($url, $content).Result
$Result.EnsureSuccessStatusCode()

I had many files to upload with each request, so I factored out this last bit into a lambda function:

function Add-FormFile {
param ([string]$Path, [string]$Name)

if ($Path -ne "")
{
$FileStream = [System.IO.File]::OpenRead($Path)
$FileName = [System.IO.Path]::GetFileName($Path)
$FileContent = [System.Net.Http.StreamContent]::new($FileStream)
$MultipartFormData.Add($FileContent, $Name, $FileName)
}
}


[1]:

[To see links please register here]

Reply



Forum Jump:


Users browsing this thread:
1 Guest(s)

©0Day  2016 - 2023 | All Rights Reserved.  Made with    for the community. Connected through