I've got a Python script which I'm trying to convert to Powershell. The script uploads a file to Amazon S3. Along with the file, it has to send some data (the request_attibutes dict). This data gets filled from a previous request, I've got some placeholder data here.
request_attibutes = {
'AWSAccessKeyId': 'ID',
'key': 'ldskfjhasdf',
'x-amz-security-token': 'adsfsdfjkl',
'policy': 'akjsdfh',
'signature': 'askjdhf'}
http_response = requests.post(url, data=request_attibutes, files=files)
Converted to Powershell:
$request_attibutes = @{AWSAccessKeyId=$keyid; key=$document_upload_data.key; 'x-amz-security-token'= $document_upload_data.'x-amz-security-token'; policy= $document_upload_data.policy;signature= $document_upload_data.signature}
$cf=Get-Item -Path $contentfile
I'm using an array to pack the $request_attibutes and the file into a single item.
$ra=@($request_attibutes2,$cf)
$response2 = Invoke-WebRequest -Uri $uploadurl -Method Post -Body $ra
The server responds with (412) Precondition Failed. So there's something the server doesn't expect. But what?
I ended up building the request body by hand:
$boundary = [System.Guid]::NewGuid().ToString();
$LF = "`r`n";
$bodyLines = (
"--$boundary",
"Content-Disposition: form-data; name=`"key`";",
"Content-Type: text$LF",
"$contentuploadpath",
"--$boundary",
"Content-Disposition: form-data; name=`"AWSAccessKeyId`";",
"Content-Type: text$LF",
$document_upload_data.awsaccesskeyid,
"--$boundary",
"Content-Disposition: form-data; name=`"policy`";",
"Content-Type: text$LF",
$document_upload_data.policy,
"--$boundary",
"Content-Disposition: form-data; name=`"signature`";",
"Content-Type: text$LF",
$document_upload_data.signature,
"--$boundary",
"Content-Disposition: form-data; name=`"x-amz-security-token`";",
"Content-Type: text$LF",
$document_upload_data.'x-amz-security-token',
"--$boundary",
"Content-Disposition: form-data; name=`"file`"; filename=`"$contentfilename`"",
"Content-Type: application/octet-stream$LF",
$fileEnc,
"--$boundary--$LF"
) -join $LF
That resulted in an output that looked identical to the Python script I was trying to replicate, but I still got server errors on the upload.
So I switched from Invoke-WebRequest
to Invoke-RestMethod
:
Invoke-RestMethod -Uri $uploadurl -Method Post -ContentType "multipart/form-data; boundary=`"$boundary`"" -Body $bodyLines
Now it works, unfortunately in PS 5 Invoke-RestMethod does not return the server response so I'm uploading blindly. At the server we can see the data coming in though.