2

I'm trying to upload a file to an ASP.NET Core API using PowerShell. My problem is that the API returns a status code 400 saying that form values are missing. Here's my PowerShell code:

add-type -AssemblyName System.Net.Http
$boundary = [System.Guid]::NewGuid().ToString()

$multipartContent = [System.Net.Http.MultipartFormDataContent]::new($boundary)
$multipartContent.Headers.Remove("Content-Type")
$multipartContent.Headers.TryAddWithoutValidation("Content-Type", "multipart/form-data; boundary=`"$boundary`"")

$stringContent = [System.Net.Http.StringContent]::new("This is a file I'm uploading")
$multipartContent.Add($stringContent, "Description")

$FilePath = "c:\path\to\file.json"
$FileStream = [System.IO.File]::OpenRead($FilePath)
$streamContent = [System.Net.Http.StreamContent]::new($FileStream)
$streamContent.Headers.ContentType = "application/json"
$multipartContent.Add($streamContent, "TheFile", "file.json")

$body = $multipartContent

$response = Invoke-RestMethod 'https://myapi.com/uploadfile' -Method 'POST' -Body $body

The code is pretty much migrated from a C# sample I have and is working. Can anyone see what I am doing wrong there?

4
  • Does this help? Commented Aug 6, 2021 at 8:27
  • I did try that approach actually. It generates a string that is too long. And I would like to use the code above (if possible) to make it match the C# sample I have too. Commented Aug 6, 2021 at 8:31
  • Last time I checked the Web cmdlets in PowerShell did not directly support mutlipart/form-data and most of the working examples create some kind of http template for the -Body parameter. Your other option if you want to keep it as close as possible to the C# code you have is to use HttpClient or whatever you are currently using instead of the web cmdlets. Commented Aug 6, 2021 at 8:47
  • 1
    You're right. PowerShell doesn't support the code I'm writing. And now I got my code working with the example you provided. Thank you so much. Feel free to publish in answer and I can mark it as the right answer. I can put my code in your answer once it is created. Commented Aug 6, 2021 at 9:12

1 Answer 1

2

As per my comment above, the Web cmdlets in PowerShell did not directly support mutlipart/form-data last I checked and most of the working examples create some kind of http template for the -Body parameter.

Here's a working sample:

$boundary = [System.Guid]::NewGuid().ToString()
$FilePath = "c:\path\to\file.json"
$TheFile = [System.IO.File]::ReadAllBytes($FilePath)
$TheFileContent = [System.Text.Encoding]::GetEncoding('iso-8859-1').GetString($TheFile)

$LF = "`r`n"
$bodyLines = (
    "--$boundary",
    "Content-Disposition: form-data; name=`"Description`"$LF",
    "This is a file I'm uploading",
    "--$boundary",
    "Content-Disposition: form-data; name=`"TheFile`"; filename=`"file.json`"",
    "Content-Type: application/json$LF",
    $TheFileContent,
    "--$boundary--$LF"
) -join $LF

Invoke-RestMethod 'https://myapi.com/uploadfile' -Method POST -ContentType "multipart/form-data; boundary=`"$boundary`"" -Body $bodyLines

Your other option if you want to keep it as close as possible to the C# code you have is to use HttpClient or whatever you are currently using instead of the web cmdlets in PowerShell.


Update: PowerShell 7+ does include a -Form parameter on both Web Cmdlets. Please see the linked examples from the official documentation:

Sign up to request clarification or add additional context in comments.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.