Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

powershell invoke-restmethod multipart/form-data

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 https://server/api/

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. https://www.snip2code.com/Snippet/396726/PowerShell-V3-Multipart-formdata-example 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!

like image 423
maigelnight Avatar asked Mar 28 '16 18:03

maigelnight


People also ask

What does Invoke-RestMethod return?

Description. The Invoke-RestMethod cmdlet sends HTTP and HTTPS requests to Representational State Transfer (REST) web services that return richly structured data. PowerShell formats the response based to the data type. For an RSS or ATOM feed, PowerShell returns the Item or Entry XML nodes.

What is the difference between invoke-RestMethod and invoke WebRequest?

Invoke-RestMethod is perfect for quick APIs that have no special response information such as Headers or Status Codes, whereas Invoke-WebRequest gives you full access to the Response object and all the details it provides.

How do I run a REST API in PowerShell?

To call a REST API from the Windows PowerShell, you should use the Invoke-RestMethod cmdlet. A call to an API is simply a request through HTTP or HTTPS. So, you will need a URL to which the API will be sent. You can find detailed information about the URL to call to get data from API documentation.


2 Answers

@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, 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
like image 178
jklemmack Avatar answered Sep 17 '22 13:09

jklemmack


It should be pretty straight forward. Taking from this answer:

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

like image 45
Bacon Bits Avatar answered Sep 20 '22 13:09

Bacon Bits