I have found a solution to my problem after studying how multipart/form-data is built. A lot of help came in the form of http://www.paraesthesia.com/archive/2009/12/16/posting-multipartform-data-using-.net-webrequest.aspx.
The solution then is to build the body of the request up manually according to that convention. I have left of niceties like correct Content-Lengths etc.
Here is an excerpt of what I am using now:
$path = "/Some/path/to/data/"
$boundary_id = Get-Date -Format yyyyMMddhhmmssfffffff
$boundary = "------------------------------" + $boundary_id
$url = "http://..."
[System.Net.HttpWebRequest] $req = [System.Net.WebRequest]::create($url)
$req.Method = "POST"
$req.ContentType = "multipart/form-data; boundary=$boundary"
$ContentLength = 0
$req.TimeOut = 50000
$reqst = $req.getRequestStream()
<#
Any time you write a file to the request stream (for upload), you'll write:
Two dashes.
Your boundary.
One CRLF (\r\n).
A content-disposition header that tells the name of the form field corresponding to the file and the name of the file. That looks like:
Content-Disposition: form-data; name="yourformfieldname"; filename="somefile.jpg"
One CRLF.
A content-type header that says what the MIME type of the file is. That looks like:
Content-Type: image/jpg
Two CRLFs.
The entire contents of the file, byte for byte. It's OK to include binary content here. Don't base-64 encode it or anything, just stream it on in.
One CRLF.
#>
<# Upload #1: XFA #>
$xfabuffer = [System.IO.File]::ReadAllBytes("$path\P7-T.xml")
<# part-header #>
$header = "--$boundary`r`nContent-Disposition: form-data; name=`"xfa`"; filename=`"xfa`"`r`nContent-Type: text/xml`r`n`r`n"
$buffer = [Text.Encoding]::ascii.getbytes($header)
$reqst.write($buffer, 0, $buffer.length)
$ContentLength = $ContentLength + $buffer.length
<# part-data #>
$reqst.write($xfabuffer, 0, $xfabuffer.length)
$ContentLength = $ContentLength + $xfabuffer.length
<# part-separator "One CRLF" #>
$terminal = "`r`n"
$buffer = [Text.Encoding]::ascii.getbytes($terminal)
$reqst.write($buffer, 0, $buffer.length)
$ContentLength = $ContentLength + $buffer.length
<# Upload #1: PDF template #>
$pdfbuffer = [System.IO.File]::ReadAllBytes("$path\P7-T.pdf")
<# part-header #>
$header = "--$boundary`r`nContent-Disposition: form-data; name=`"pdf`"; filename=`"pdf`"`r`nContent-Type: application/pdf`r`n`r`n"
$buffer = [Text.Encoding]::ascii.getbytes($header)
$reqst.write($buffer, 0, $buffer.length)
$ContentLength = $ContentLength + $buffer.length
<# part-data #>
$reqst.write($pdfbuffer, 0, $pdfbuffer.length)
$ContentLength = $ContentLength + $pdfbuffer.length
<# part-separator "One CRLF" #>
$terminal = "`r`n"
$buffer = [Text.Encoding]::ascii.getbytes($terminal)
$reqst.write($buffer, 0, $buffer.length)
$ContentLength = $ContentLength + $buffer.length
<#
At the end of your request, after writing all of your fields and files to the request, you'll write:
Two dashes.
Your boundary.
Two more dashes.
#>
$terminal = "--$boundary--"
$buffer = [Text.Encoding]::ascii.getbytes($terminal)
$reqst.write($buffer, 0, $buffer.length)
$ContentLength = $ContentLength + $buffer.length
$reqst.flush()
$reqst.close()
# Dump request to console
#$req
[net.httpWebResponse] $res = $req.getResponse()
# Dump result to console
#$res
# Dump result-body to filesystem
<#
$resst = $res.getResponseStream()
$sr = New-Object IO.StreamReader($resst)
$result = $sr.ReadToEnd()
$res.close()
#>
$null = New-Item -ItemType Directory -Force -Path "$path\result"
$target = "$path\result\P7-T.pdf"
# Create a stream to write to the file system.
$targetfile = [System.IO.File]::Create($target)
# Create the buffer for copying data.
$buffer = New-Object Byte[] 1024
# Get a reference to the response stream (System.IO.Stream).
$resst = $res.GetResponseStream()
# In an iteration...
Do {
# ...attemt to read one kilobyte of data from the web response stream.
$read = $resst.Read($buffer, 0, $buffer.Length)
# Write the just-read bytes to the target file.
$targetfile.Write($buffer, 0, $read)
# Iterate while there's still data on the web response stream.
} While ($read -gt 0)
# Close the stream.
$resst.Close()
$resst.Dispose()
# Flush and close the writer.
$targetfile.Flush()
$targetfile.Close()
$targetfile.Dispose()