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:
  • 374 Vote(s) - 3.49 Average
  • 1
  • 2
  • 3
  • 4
  • 5
powershell invoke-restmethod multipart/form-data

#1
I'm currently trying to upload a file to a Webserver by using a REST API. And as mentioned I'm using PowerShell for this. With curl this is no problem. The call looks like this:

curl -H "Auth_token:"$AUTH_TOKEN -H "Content-Type:multipart/form-data" -X POST -F appInfo='{"name": "test","description": "test"}' -F uploadFile=@/test/test.test

[To see links please register here]


But I'm completely helpless when it comes to exporting this to powershell with a Invoke-Restmethod command. As far as I searched it is not possible to use the Invoke-Restmethod for this.

[To see links please register here]

But even with that Snipped I'm not smart enough to get this working since I don´t want to upload two files but instead one file and some arguments.

I would be very thankful if someone could get me back on the track with this :o
Thanks!
Reply

#2
It should be pretty straight forward. Taking from [this answer](

[To see links please register here]

):

$Uri = 'https://server/api/';
$Headers = @{'Auth_token'=$AUTH_TOKEN};
$FileContent = [IO.File]::ReadAllText('C:\test\test.test');
$Fields = @{'appInfo'='{"name": "test","description": "test"}';'uploadFile'=$FileContent};

Invoke-RestMethod -Uri $Uri -ContentType 'multipart/form-data' -Method Post -Headers $Headers -Body $Fields;

You may want to use `[IO.File]::ReadAllBytes()` if the file isn't a text file.

This also may not work well if you're uploading a huge file.
Reply

#3
@Bacon-Bits answer didn't seem to work for me. My server rejected it with a potentially malformed form-data body :-(

I found [this gist][1], and trimmed it up a bit for my purposes. Here's my end result:



$FilePath = 'c:\temp\temp.txt';
$URL = 'http://your.url.here';

$fileBytes = [System.IO.File]::ReadAllBytes($FilePath);
$fileEnc = [System.Text.Encoding]::GetEncoding('UTF-8').GetString($fileBytes);
$boundary = [System.Guid]::NewGuid().ToString();
$LF = "`r`n";

$bodyLines = (
"--$boundary",
"Content-Disposition: form-data; name=`"file`"; filename=`"temp.txt`"",
"Content-Type: application/octet-stream$LF",
$fileEnc,
"--$boundary--$LF"
) -join $LF

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


[1]:
Reply

#4
So, I've battled with this quite a bit lately and discovered it is indeed possible to match curl functionality, but it's not immediately obvious how to do multipart/form-data correctly. All the responses above have covered important pieces of the puzzle, but I'm going to try and tie it all together here for the next sorry fellow who is trying to implement curl functionality in native Powershell.

[@jklemmack's](

[To see links please register here]

) solution is the one that put me on the right track, and is the most flexible, because it allows you to construct the form-data content specifically, controlling both the boundaries, along with how the data gets formatted within it.

For anyone trying to do this, I think it's important that you arm yourself with a proper web debugging proxy like Fiddler (.net) or Burp Suite (java), so that you can inspect each of the REST calls in detail to understand the specific format of the data being passed across to the API.

In my specific case, I noticed that curl was inserting a blank line above each part of the form data - so to extend @jklemmack's example, it would look like the following:

```
$bodyLines = (
"--$boundary",
"Content-Disposition: form-data; name=`"formfield1`"",
'',
$formdata1,
"--$boundary",
"Content-Disposition: form-data; name=`"formfield2`"",
'',
$formdata2,
"--$boundary",
"Content-Disposition: form-data; name=`"formfield3`"; filename=`"$name_of_file_being_uploaded`"",
"Content-Type: application/json",
'',
$content_of_file_being_uploaded,
"--$boundary--"
) -join $LF

```

Hope this saves someone a lot of time in the future!

I also still agree that if you need to do this from scratch, and have the option of using the curl native binary directly (while ensuring due-diligence around security and compliance), that you take advantage of it's maturity and the conveniences that it provides. Use curl. It is better that this multipart logic be vigourously tested and maintained by the curl community at large, vs the onus being on your internal dev or operations teams.
Reply

#5
With PowerShell Core this should work out of the box with the new `-Form` parameter.

See:

[To see links please register here]


```
$Uri = 'https://api.contoso.com/v2/profile'
$Form = @{
firstName = 'John'
lastName = 'Doe'
email = '[email protected]'
avatar = Get-Item -Path 'c:\Pictures\jdoe.png'
birthday = '1980-10-15'
hobbies = 'Hiking','Fishing','Jogging'
}
$Result = Invoke-RestMethod -Uri $Uri -Method Post -Form $Form
```
Reply

#6
I needed to pass both the header and some more parameters (`insert=true` and `debug=true`) along with the file content. Here's my version which extends the script by @jklemmack.

```psh
param([string]$path)

$Headers = @{Authorization = "Bearer ***************"}
$Uri = 'https://host:8443/api/upload'

$fileBytes = [System.IO.File]::ReadAllBytes($path);
$fileEnc = [System.Text.Encoding]::GetEncoding('ISO-8859-1').GetString($fileBytes);
$boundary = [System.Guid]::NewGuid().ToString();
$LF = "`r`n";

$bodyLines = (
"--$boundary",
"Content-Disposition: form-data; name=`"insert`"$LF",
"true$LF",
"--$boundary",
"Content-Disposition: form-data; name=`"debug`"$LF",
"true$LF",
"--$boundary",
"Content-Disposition: form-data; name=`"file`"; filename=`"$path`"",
"Content-Type: application/octet-stream$LF",
$fileEnc,
"--$boundary--$LF"
) -join $LF

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

#7
Such pain trying to get a powershell v4 on windows 8.1 to upload files to my upload.php

```
# This code works and matches to a Firefox 78.6.0esr upload transmission verified via wireshark

$FilePath = 'c:\Temp\file-to-upload.txt';
$URL = 'http://127.0.0.1/upload.php';

$fileBytes = [System.IO.File]::ReadAllBytes($FilePath);
$fileEnc = [System.Text.Encoding]::GetEncoding('UTF-8').GetString($fileBytes);
$boundary = [System.Guid]::NewGuid().ToString();
$LF = "\r\n";

$bodyLines = "--$boundary $LF Content-Disposition: form-data; name='file'; filename='file-to-upload.txt' $LF Content-Type: application/octet-stream $LF $fileEnc $LF --$boundary-- $LF";

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

For reference, the upload.php is:
```
<?php
$uploaddir = '/var/www/uploads/';
$uploadfile = $uploaddir . $_FILES['file']['name'];
move_uploaded_file($_FILES['file']['tmp_name'], $uploadfile)
?>
```

Wireshark Sample
```
POST /upload.php HTTP/1.1
User-Agent: Mozilla/5.0 (Windows NT; Windows NT 6.3; en-US) WindowsPowerShell/4.0
Content-Type: multipart/form-data; boundary=96985b62-451a-41fa-9eca-617e3599797c
Host: 127.0.0.1
Content-Length: 284
Connection: Keep-Alive

--96985b62-451a-41fa-9eca-617e3599797c \r\n Content-Disposition: form-data; name='file'; filename='ftp.txt' \r\n Content-Type: application/octet-stream \r\n open 127.0.0.1 21
anonymous
anonymous
bin
put file-to-upload.txt
quit
\r\n --96985b62-451a-41fa-9eca-617e3599797c-- \r\nHTTP/1.1 200 OK
Date: Sat, 02 Jan 2021 22:11:03 GMT
Server: Apache/2.4.46 (Debian)
Content-Length: 0
Keep-Alive: timeout=5, max=100
Connection: Keep-Alive
Content-Type: text/html; charset=UTF-8

```


Reply

#8
*There was lot of hacky code required to do this and most of the answers here are just stating them. These answers should be either deleted or archived along with all hacky blogs over the internet.*

With latest version (PowerShell Core v7.2.6 as of this writing). All you need is to give Path using Get-Item-Path.

$Form = @{
document= Get-Item -Path .\image.png # no leading @ sign.
}

$Result = Invoke-RestMethod -Uri $Uri -Method Post -Form $Form

**Please note that there is no @ sign before get item like you put in curl. I was putting @ sign and breaking my request.**

reference :

[To see links please register here]

Reply

#9
I had some troubles trying to do the following `curl` command using [`Invoke-RestMethod`](

[To see links please register here]

):

<!-- language: lang-bash -->

curl --request POST \
--url

[To see links please register here]

\
--header 'content-type: multipart/form-data' \
--form '[email protected]'
-v

In my case, it turned out to be easier to use `curl` with powershell.

<!-- language: lang-powershell -->

$FilePath = "C:\example.csv"
$CurlExecutable = "C:\curl-7.54.1-win64-mingw\bin\curl.exe"

$CurlArguments = '--request', 'POST',
'https://example.com/upload_endpoint/',
'--header', "'content-type: multipart/form-data'",
'--form', "file=@$FilePath"
'-v',

# Debug the above variables to see what's going to be executed
Write-Host "FilePath" $FilePath
Write-Host "CurlExecutable" $FilePath
Write-Host "CurlArguments" $CurlArguments

# Execute the curl command with its arguments
& $CurlExecutable @CurlArguments

Download the executable for your os on [curl's website](

[To see links please register here]

).

Here are some reasons that _could_ make you pick `curl` instead of powershell's `invoke-restmethod`

* Many of the tools out there can generate curl commands
* curl supports uploading files larger than 2GB (see [Shukri Adams comment][1])

Both Curl and Powershell's `invoke-restmethod` are fine solutions. You might want to consider `curl` if none of the other answers worked for you. It is usually better to stick with built-in solutions, but sometimes alternatives can be useful.


[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