Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
PowerShell V3 Multipart/formdata example with REST-API (Invoke-RestMethod)
function Import-Portatour {
param (
[parameter(Mandatory=$True,Position=1)] [ValidateScript({ Test-Path -PathType Leaf $_ })] [String] $FilePath,
[parameter(Mandatory=$False,Position=2)] [System.URI] $ResultURL
)
# CONST
$CODEPAGE = "iso-8859-1" # alternatives are ASCII, UTF-8
# We have a REST-Endpoint
$RESTURL = "https://my.portatour.net/a/api/ImportCustomers/"
# Testing
$userEmail = "some.user@example.org"
# Read file byte-by-byte
$fileBin = [System.IO.File]::ReadAllBytes($FilePath)
# Convert byte-array to string
$enc = [System.Text.Encoding]::GetEncoding($CODEPAGE)
$fileEnc = $enc.GetString($fileBin)
# Read a second hardcoded file which we want to upload through the API call
$importConfigFileEnc = $enc.GetString([System.IO.File]::ReadAllBytes("C:\Users\xyz\Documents\WindowsPowerShell\portatour.importcfg"))
# Create Object for Credentials
$user = "Username"
$pass = "Passw0rd"
$secpasswd = ConvertTo-SecureString $pass -AsPlainText -Force
$cred = New-Object System.Management.Automation.PSCredential ($user, $secpasswd)
# We need a boundary (something random() will do best)
$boundary = [System.Guid]::NewGuid().ToString()
# Linefeed character
$LF = "`r`n"
# Build up URI for the API-call
$uri = $RESTURL + "?userEmail=$userEmail&mode=UpdateOrInsert"
# Build Body for our form-data manually since PS does not support multipart/form-data out of the box
$bodyLines = (
"--$boundary",
"Content-Disposition: form-data; name=`"file`"; filename=`"Import.xlsx`"",
"Content-Type: application/octet-stream$LF",
$fileEnc,
"--$boundary",
"Content-Disposition: form-data; name=`"importConfig`"; filename=`"portatour.importcfg`"",
"Content-Type: application/octet-stream$LF",
$importConfigFileEnc,
"--$boundary--$LF"
) -join $LF
try {
# Submit form-data with Invoke-RestMethod-Cmdlet
Invoke-RestMethod -Uri $uri -Method Post -ContentType "multipart/form-data; boundary=`"$boundary`"" -Body $bodyLines -Credential $cred
}
# In case of emergency...
catch [System.Net.WebException] {
Write-Error( "REST-API-Call failed for '$URL': $_" )
throw $_
}
}
@weipah

This comment has been minimized.

Copy link
Owner Author

weipah commented Mar 9, 2015

Attention: Invoke-RestMethod is only available since PowerShell 3.0 (Win8/WinSrv 2012); Win7 / 2008R2 can be updated
Initial Source: http://stackoverflow.com/questions/25075010/upload-multiple-files-from-powershell-script

  • This is the first working draft
@sujangrg

This comment has been minimized.

Copy link

sujangrg commented May 19, 2017

Thanks. This works perfect, at least for me :)

@Shaimaaiti

This comment has been minimized.

Copy link

Shaimaaiti commented Jul 2, 2017

really thanks, that helps me more

@dmichine

This comment has been minimized.

Copy link

dmichine commented Sep 5, 2017

Thanks, was of great help. However I did have an issue around the boundary in the header

Invoke-RestMethod -Uri $uri -Method Post -ContentType "multipart/form-data; boundary="$boundary""

I've had to remove the quotes around $boundary for it to work

Invoke-RestMethod -Uri $uri -Method POST -ContentType "multipart/form-data; boundary=$boundary"

@AndrewPla

This comment has been minimized.

Copy link

AndrewPla commented Sep 25, 2018

Thanks for sharing this gist, it definitely helped me out. This is what I came up with

   $file = "c:\file.txt"

    $fileName = Split-Path $File 
    $boundary = [guid]::NewGuid().ToString()

    $fileBin = [System.IO.File]::ReadAllBytes($File)

    $enc = [System.Text.Encoding]::GetEncoding("iso-8859-1")

    $fileEnc = $enc.GetString($fileBin)

    $bodyLines = @(

        "--$boundary",

        "Content-Disposition: form-data; name=`"file`"; filename=`"$filename`"",

        "Content-Type: application/octet-stream$LF",

        $fileEnc,

        "--$boundary",

        "Content-Disposition: form-data; name=`"importConfig`"; filename=`"portatour.importcfg`"",

        "Content-Type: application/octet-stream$LF",

        $importConfigFileEnc,

        "--$boundary--$LF"

    ) -join $LF
      $Headers = @{
            'Authorization' = $LoginToken
        }
    $params = @{
        Uri         = $Uri
        Body        = $bodyLines
        Method      = 'Post'
        Headers     = $headers
        ContentType = "multipart/form-data; boundary=$boundary"
    }
    Invoke-RestMethod @params

`

@tjhiisager

This comment has been minimized.

Copy link

tjhiisager commented Nov 20, 2018

I still having problem with file upload, can anyone try to help me, i got this
$CurlExecutable = "C:\Delphix\curl.exe"
$CurlArguments = '-l',
$url,
'--header', """content-type: multipart/form-data""",
'--header', """Authorization: ab2aac30-91b3-4790-8fda-80970dbadf33""",
'--form', "fileFormat=@e:\Tools\Powershell\Delphix\Masking\FileFormats\BS_REC00002_CSV.FF",
'--form', "fileFormatType=DELIMITED" ,
'-s'

@(& $CurlExecutable @CurlArguments)

And thats Work, but i would like to convert it to invoke-restmethod (to get rid of curl)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.