Upload document to Salesforce using powershell - powershell

I'm trying to upload a text file in our Salesforce application using PowerShell.
The curl code which I'm trying to mimic in PowerShell is:
curl -X POST -H "Authorization: {SESSION_ID}" \
-H "Content-Type: multipart/form-data" \
-F file=#document.txt \
-F "name__v=myDocument" \
-F "type__v=Undefined" \
-F "lifecycle__v=Unclassified" \
https://{server}/api/{version}/objects/documents
Here is the PowerShell code which I have written taking hint from the web:
$URL="https://{server}/api/{version}/auth"
$CT="application/x-www-form-urlencoded"
$User="user"
$Password="pass"
$SessionID=(Invoke-RestMethod -Method Post -Uri $URL -Body #{"Content-Type" = $CT; "username" = $User; "password" = $Password}).sessionId
$URL="https://{server}/api/{version}/objects/documents"
$boundary=[System.Guid]::NewGuid().ToString()
$LF="`r`n"
$File=Get-Content("....\test.txt")
$fileBin=[System.IO.File]::ReadAllBytes("....\test.txt")
$enc=[System.Text.Encoding]::GetEncoding("iso-8859-1")
$fileEnc=$enc.GetString($fileBin)
$Body1=(
"--$boundary",
"Content-Disposition: form-data; name__v=`"kaz.txt`"; type__v=`"Undefined`"; lifecycle__v=`"Unclassified`"",
"Content-Type: application/octet-stream$LF",
$fileEnc,
"--$boundary--$LF"
) -join $LF
$Body2 = (
"file=$File; name__v=`"kaz.txt`"; type__v=`"Undefined`"; lifecycle__v=`"Unclassified`""
)
Invoke-RestMethod -Method POST -Uri $URL -Headers #{"Authorization" = $SessionID; "Content-Type" = "multipart/form-data; boundary=`"$boundary`""} -Body $Body1
Invoke-RestMethod -Method POST -Uri $URL -Headers #{"Authorization" = $SessionID; "Content-Type" = "multipart/form-data; boundary=`"$boundary`""} -Body $Body2
None of these are working and I'm getting error
PARAMETER_REQUIRED lifecycle__v: Missing required parameter : lifecycle__v.

I modified the body and now its working fine
$Body = (
"--$boundary", "Content-Disposition: form-data; name=`"file`"; filename=`"test.docx`"", "Content-Type: application/octet-stream$LF", $fileEnc,
"--$boundary", "Content-Disposition: form-data; name=`"lifecycle__v`"", "", "Unclassified",
"--$boundary", "Content-Disposition: form-data; name=`"type__v`"", "", "Undefined",
"--$boundary--"
)-join $LF
Invoke-RestMethod -Method POST -Uri $URL -Headers #{"Authorization" = $SessionID; "Content-Type" = "multipart/form-data; boundary=$boundary"} -Body $Body

Related

File upload via Pipedrive API

I need to include the lead_id in the body with the file content. The file uploads well when I use
$data = Invoke-RestMethod -Uri $URL -Method 'Post' -ContentType "multipart/form-data; boundary=`"$boundary`"" -Body $BodyLines.
Naturally the file is not attached to the lead. When I use
$data = Invoke-RestMethod -Uri $URL -Method 'Post' -ContentType "multipart/form-data; boundary=`"$boundary`"" -Body $Body
I always get error 400. Specification of $Body is wrong, but how?
#URL for Deal listing with your $company_domain and $api_token variables
$URL = 'https://' + $company_domain + '.pipedrive.com/api/v1/files?api_token=' + $api_token
$URL
#
$FilePath = $LOCALpath + "\webtilaus\Tarjouspyynto_2023-02-03_09-50-44.txt"
$data =#()
$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
$Body = #{
"deal_id" = "25"
"file" = $bodyLines
}
$data = Invoke-RestMethod -Uri $URL -Method 'Post' -ContentType "multipart/form-data; boundary=`"$boundary`"" -Body $BodyLines # This uploads
$data = Invoke-RestMethod -Uri $URL -Method 'Post' -ContentType "multipart/form-data; boundary=`"$boundary`"" -Body $Body # This gives error 400`

Multform data for Invoke-Restmethod giving 405 Powershell

Below is the curl command which i translated in to Powershell but when i execute it i get 405, can any one help
curl --location --request POST 'https://anypoint.com/hybrid/api/v1/applications' \
--header 'X-ANYPNT-ENV-ID: 4a961b64' \
--header 'X-ANYPNT-ORG-ID: c6589234ad' \
--header 'Authorization: Bearer c83605e456432e6' \
--form 'artifactName="TEST-DEVOPS-SC"' \
--form 'targetId="12073594"' \
--form 'application="{\"configuration\":{}}"' \
--form 'file=#"/C:/Users/vada/Downloads/documents-v1-1.0.2.application.jar"'
Powershell
$Headers = #{
'Authorization' = "Bearer $($Token.access_token)"
'X-ANYPNT-ENV-ID' = '4a96ab37cf1b64'
'X-ANYPNT-ORG-ID' = 'c658379234ad'
}
Write-Host $Headers.Authorization
$path = "E:\actionsdocuments\documents\target\documents-v1-1.0.2-application.jar";
$file_name=$path.split('\')[-1]
$domain_id= 11312492
$Uri = "https://anypoint.com/hybrid/api/v1/applications/$domain_id"
$fileBytes = [System.IO.File]::ReadAllBytes($path);
$fileEnc = [System.Text.Encoding]::GetEncoding('ISO-8859-1').GetString($fileBytes);
#$jsonfile = [System.IO.File]::ReadAllBytes($jsonpath)
#$jsonEnc = [System.Text.Encoding]::GetEncoding('ISO-8859-1').GetString($jsonfile);
$boundary = [System.Guid]::NewGuid().ToString();
$LF = "`r`n";
$bodyLines = (
"--$boundary",
"Content-Disposition: form-data; name=`"artifactName`"$LF",
"TEST-DEVOPS-ONPREM$LF",
"--$boundary",
"Content-Disposition: form-data; name=`"targetId`"$LF",
"12073594$LF",
"--$boundary",
"Content-Disposition: form-data; name=`"application`"$LF",
"{`"configuration`":{}}$LF",
"--$boundary",
"Content-Disposition: form-data; name=`"file`"; filename=`"$file_name`"",
"Content-Type: application/octet-stream$LF",
$fileEnc,
"--$boundary--$LF"
) -join $LF
$response= Invoke-RestMethod -Uri $Uri -Headers $Headers -Method POST -ContentType "multipart/form-data; boundary=`"$boundary`"" -Body $bodyLines
Error
Invoke-RestMethod : {"message":"HTTP 405 Method Not Allowed"}
At line:63 char:12
$response= Invoke-RestMethod -Uri $Uri -Headers $Headers -Method POST ...
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
CategoryInfo : InvalidOperation: (System.Net.HttpWebRequest:HttpWebRequest) [Invoke-RestMethod], WebException
FullyQualifiedErrorId : WebCmdletWebResponseException,Microsoft.PowerShell.Commands.InvokeRestMethodCommand

Curl To Powershell - Click Send

I am struggling with this code as I have never encountered
Here is the Example code that click send provides.
curl --include \
--header "Authorization: Basic YXBpLXVzZXJuYW1lOmFwaS1wYXNzd29yZA==" \
--request POST \
--header "Content-Type: application/x-www-form-urlencoded" \
--data-binary "username=myusername&key=1234-I3U2RN34IU-43UNG&to=61411111111,64122222222,61433333333&senderid=example&message=testing" \
'https://api-mapper.clicksend.com/http/v2/send.php'
URL: https://developers.clicksend.com/docs/http/v2/#send-an-sms
Here is what I have figured out so far:
$BaseURL = "https://api-mapper.clicksend.com/http/v2/send.php"
$Header = #{
"Authorization" = "Basic"+[System.Convert]::ToBase64String([System.Text.Encoding]::UTF8.GetBytes("$APIKey"))
}
$body = #{
"useranme"="$Username"
"key"="$APIKey"
"to"="$To"
"senderid"="$from"
"message"=$Message
}
$Return = Invoke-RestMethod -Method Post -Headers $Header -ContentType "application/x-www-form-urlencoded" -Uri $BaseURL -Body $body
$return.InnerXml
I'm stuck on the --data-binary part of the code.
I believe using the --data-binary in curl is like creating a string in the body of the request:
$BaseURL = "https://api-mapper.clicksend.com/http/v2/send.php"
$Username = "Username"
$APIKey = "SomeAPIKey"
$To = "Recipient"
$From = "Sender"
$Message = "MessageFoRecipient"
$Header = #{
"Authorization" = "Basic"+ " " + ([System.Convert]::ToBase64String([System.Text.Encoding]::UTF8.GetBytes("$APIKey")))
}
$body = "username=$Username" + "&" + "key=$APIKey" + "&" + "to=$To" + "&" + "senderid=$From" + "&" + "message=$Message"
$return = Invoke-RestMethod -Method Post -Headers $Header -ContentType "application/x-www-form-urlencoded" -Uri $BaseURL -Body $body
$return.InnerXml
Invoke-RestMethod assumes that you want your POST body to be application/x-www-form-urlencoded (unless otherwise specified, e.g. XML, JSON).  You must be having an issue with something such as the fact that the Authorization header doesn't have a space between Basic and the Base64 string, or the fact that username has a typo.
$BaseURL = 'http://localhost:8000'
$Username = 'api-username'
$ApiKey = 'api-password'
$To = '61411111111,64122222222,61433333333'
$From = 'example'
$Message = 'testing'
$SenderId = 'example'
$Body = #{
username = $Username
key = $ApiKey
to = $To
senderid = $SenderId
message = $Message
}
$Header = #{
Authorization = 'Basic ' + ([System.Convert]::ToBase64String([System.Text.Encoding]::UTF8.GetBytes("$APIKey")))
}
$Return = Invoke-RestMethod -Method Post -Headers $Header -Uri $BaseURL -Body $Body
$Return.InnerXml
Yields the following HTTP request:
POST / HTTP/1.1
Host: localhost:8000
Authorization: Basic YXBpLXBhc3N3b3Jk
User-Agent: Mozilla/5.0 (Windows NT 10.0; Microsoft Windows 10.0.19042; en-US) PowerShell/7.2.1
Content-Length: 112
Content-Type: application/x-www-form-urlencoded
key=api-password&message=testing&username=api-username&to=61411111111%2C64122222222%2C61433333333&sender=example

CURL - Powershell : Invoke-RestMethod to GLPI API : Upload Document

I would like to upload a file to my GLPI from API.
This curl command works fine :
curl -X POST
-H 'Content-Type: multipart/form-data'
-H 'Session-Token: $sessiontoken'
-H 'App-Token:$apptoken'
-F 'uploadManifest={"input": {"name": "Uploaded document", "_filename" : ["file.txt"]}};type=application/json'
-F 'filename[0]=#file.txt' 'http://GLPI_SERVER/glpi/apirest.php/Document'
The same curl in powershell (Thank's to Jean-Christophe from GLPI) :
$DocumentUpload = C:\curl\bin\curl.exe `
-X POST `
-H 'Content-Type: multipart/form-data' `
-H "Session-Token: $($SessionToken.session_token)" `
-H 'App-Token: '$AppToken `
-F 'uploadManifest={\"input\": {\"name\": \"Document ticket 161\", \"_filename\" : [\"clear.png\"], \"tickets_id\":\"161\"}};type=application/json' `
-F 'filename[0]=#"C:\temp1\clear.png"' `
-s `
-k 'https://glpi.xxxx.fr/apirest.php/Document/'
I would like use the Invoke-RestMethod but without success
# GLPI REST API CONFIG :
$AppURL = "https://glpi.xxxxxxxxxxxx.fr/apirest.php"
$UserToken = "zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz"
$AppToken = "XXXXXXXXXXX"
$ID = 161
$ItemType = "Ticket"
$SubItemType = "Document"
$manifest = #{}
$SessionToken = Invoke-RestMethod "$AppURL/initSession" -Method Get -Headers #{"Content-Type" = "application/json";"Authorization" = "user_token $UserToken";"App-Token"=$AppToken}
$FileContent = [System.IO.File]::ReadAllBytes("C:\temp1\clear.png")
$input = New-Object System.Collections.ArrayList
$type =New-Object System.Collections.ArrayList
$filename =New-Object System.Collections.ArrayList
$input = #{input=#{"name"="titre";"_filename"="clear.png";"tickets_id"="161"}}
$type = #{"type"="application/json"}
$filename =#{"filename[0]"="C:\temp1\clear.png"}
$manifest.Add("uploadManifest",$input)
$manifest.Add("type=","application/json")
$manifest.Add("filename[0]=",#("C:\temp1\clear.png"))
$json = #($manifest | ConvertTo-Json)
#Display Convert to JSON
#$json
Invoke-RestMethod "$AppURL/$($ItemType)/$($ID)/$($SubItemType)" -Method Post -Headers #{"session-token"=$SessionToken.session_token; "App-Token" = $AppToken} -Body ([System.Text.Encoding]::UTF8.GetBytes($json)) -ContentType 'multipart/data'
## Test autre ContentType
Invoke-RestMethod "$AppURL/$($ItemType)/$($ID)/$($SubItemType)" -Method Post -Headers #{"session-token"=$SessionToken.session_token; "App-Token" = $AppToken} -Body ([System.Text.Encoding]::UTF8.GetBytes($json)) -ContentType 'multipart/form-data'
#Kill session
Invoke-RestMethod "$AppURL/killSession" -Headers #{"session-token"=$SessionToken.session_token; "App-Token" = "$AppToken"}
The Invoke with : -ContentType 'multipart/data'
["ERROR_BAD_ARRAY","The input parameter must be an array of objects
The Invoke with : -ContentType 'multipart/form-data'
["ERROR_UPLOAD_FILE_TOO_BIG_POST_MAX_SIZE","The file seems too big"]
I thank in advance if someone sees my mistakes and help me.
Same topic to : How convert curl file upload command to Invoke-RestMethod?
press f12 in chrome to open devtools, go to network tab (probably good idea to enable XHR filter too)
manually upload file - new requests will show up in devtools
find the one that uploads file
right click - copy - as powershell
that will copy entire request that you can then adjust/review to have better idea of what goes where
Thank's for your answer Charg, but when i try there are lot of change and pages. I have try this option before post here :D. Because for me the copy is not useable. Maybe easiest for you :
I have to create a new reply because the comment does not allow enough characters.
(i have deleted headers)
Invoke-WebRequest -Uri "https://glpi.XXXXXXXXXXXX.fr/ajax/fileupload.php" `
-Method "POST" `
-Headers #{
} `
-ContentType "multipart/form-data; boundary=----WebKitFormBoundarysgETZNBiXoMdeht2Q" `
-Body ([System.Text.Encoding]::UTF8.GetBytes("------WebKitFormBoundarysgETZNBiXoMdeht2Q$([char]13)$([char]10)Content-Disposition: form-data; name=`"name`"$([char]13)$([char]10)$([char]13)$([char]10)filename$([char]13)$([char]10)------WebKitFormBoundarysgETZNBiXoMeht2Q$([char]13)$([char]10)Content-Disposition: form-data; name=`"showfilesize`"$([char]13)$([char]10)$([char]13)$([char]10)1$([char]13)$([char]10)------WebKitFormBoundarysgETZNBiXoMeht2Q$([char]13)$([char]10)Content-Disposition: form-data; name=`"filename[]`"; filename=`"apple.png`"$([char]13)$([char]10)Content-Type: image/png$([char]13)$([char]10)$([char]13)$([char]10)$([char]13)$([char]10)------WebKitFormBoundarysgETZNBiXoMeht2Q--$([char]13)$([char]10)"))
And other body (more informations) :
-Body ([System.Text.Encoding]::UTF8.GetBytes("------WebKitFormBoundarymPxXKSWBW70lLtX2 $([char]13)$([char]10)Content-Disposition: form-data; name=`"documentcategories_id`"$([char]13)$([char]10)$([char]13)$([char]10)10$([char]13)$([char]10)------WebKitFormBoundarymPxXKSWBW70lLtX2$([char]13)$([char]10)Content-Disposition: form-data; name=`"entities_id`"$([char]13)$([char]10)$([char]13)$([char]10)2$([char]13)$([char]10)------WebKitFormBoundarymPxXKSWBW70lLtX2$([char]13)$([char]10)Content-Disposition: form-data; name=`"is_recursive`"$([char]13)$([char]10)$([char]13)$([char]10)0$([char]13)$([char]10)------WebKitFormBoundarymPxXKSWBW70lLtX2$([char]13)$([char]10)Content-Disposition: form-data; name=`"itemtype`"$([char]13)$([char]10)$([char]13)$([char]10)Ticket$([char]13)$([char]10)------WebKitFormBoundarymPxXKSWBW70lLtX2$([char]13)$([char]10)Content-Disposition: form-data; name=`"items_id`"$([char]13)$([char]10)$([char]13)$([char]10)161$([char]13)$([char]10)------WebKitFormBoundarymPxXKSWBW70lLtX2$([char]13)$([char]10)Content-Disposition: form-data; name=`"tickets_id`"$([char]13)$([char]10)$([char]13)$([char]10)161$([char]13)$([char]10)------WebKitFormBoundarymPxXKSWBW70lLtX2$([char]13)$([char]10)Content-Disposition: form-data; name=`"_filename[0]`"$([char]13)$([char]10)$([char]13)$([char]10)6075d0cb639f08.69946676apple.png$([char]13)$([char]10)------WebKitFormBoundarymPxXKSWBW70lLtX2$([char]13)$([char]10)Content-Disposition: form-data; name=`"_prefix_filename[0]`"$([char]13)$([char]10)$([char]13)$([char]10)6075d0cb639f08.69946676$([char]13)$([char]10)------WebKitFormBoundarymPxXKSWBW70lLtX2$([char]13)$([char]10)Content-Disposition: form-data; name=`"_tag_filename[0]`"$([char]13)$([char]10)$([char]13)$([char]10)ea6f951c-f37490bd-6075d0cb7fc703.58112843$([char]13)$([char]10)------WebKitFormBoundarymPxXKSWBW70lLtX2$([char]13)$([char]10)Content-Disposition: form-data; name=`"filename[]`"; filename=`"`"$([char]13)$([char]10)Content-Type: application/octet-stream$([char]13)$([char]10)$([char]13)$([char]10)$([char]13)$([char]10)------WebKitFormBoundarymPxXKSWBW70lLtX2$([char]13)$([char]10)Content-Disposition: form-data; name=`"add`"$([char]13)$([char]10)$([char]13)$([char]10)Ajouter un nouveau fichier$([char]13)$([char]10)------WebKitFormBoundarymPxXKSWBW70lLtX2$([char]13)$([char]10)Content-Disposition: form-data; name=`"_glpi_csrf_token`"$([char]13)$([char]10)$([char]13)$([char]10)583040be8c019c6b482ff61d4c6c37230109cb37876001d086603c1b4a144eb0$([char]13)$([char]10)------WebKitFormBoundarymPxXKSWBW70lLtX2--$([char]13)$([char]10)"))
And I found a guy, who wrote this part in Python (maybe help to translate to powershell ?)
multipart_form_data = {
'uploadManifest': (None, '{"input": {"name": "test123.png", "_filename": ["test123.png"]}}'),
'file': ('test123.png', open('test123.png', 'rb')),
}
And one other guy find his solution in C# (i have losted the post id)
// Upload
var RSClient = new RestClient(Properties.Settings.Default.GLPI_URL);
var request = new RestRequest("Document", Method.POST);
request.AddHeader("Session-Token", Properties.Settings.Default.GLPI_SESSION_TOKEN);
request.AddHeader("App-Token", Properties.Settings.Default.GLPI_APP_TOKEN);
request.AddHeader("Accept", "application/json");
request.AddHeader("Content-Type", "multipart/form-data");
request.AddQueryParameter("uploadManifest", "{\"input\": {\"name\": \"UploadFileTest\", \"_filename\": \"GiletsJaunes.jpg\"}}");
request.AddFile("test", #"C:\path\to\File.jpg");
IRestResponse response = RSClient.Execute(request);
var content = response.Content;
textBox2.Text = textBox2.Text + Environment.NewLine + content;

Invoke-RestMethod Upload ZIP File

I try to upload a file to a uri with POST. I somehow fail. I got help from
powershell invoke-restmethod multipart/form-data
but they uploaded a text file.
Also the curl command works:
curl -X POST "https://some.place.over.the.rainbow.com/api/v1/dataupdate" -H "accept: */*" -H "Authorization: Basic 123123123123" -F "file=#/c/updates/SomeFile.zip"
In my ps1 Script I tried following:
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
$Headers = #{
Authorization = "Basic 123123123123"
};
$FilePath = "C:\Users\asd\SomeFile.zip";
$Uri = 'ttps://some.place.over.the.rainbow.com/api/v1/dataupdate';
$LF = "`r`n";
$boundary = [System.Guid]::NewGuid().ToString();
$fileBytes = [System.IO.File]::ReadAllBytes($FilePath);
$fileEnc = [System.Text.Encoding]::GetEncoding('UTF-8').GetString($fileBytes);
$bodyLines = (
"--$boundary",
"Content-Disposition: form-data; name=`"file`"; filename=`"SomeFile.zip`"",
$fileEnc,
"--$boundary--$LF"
) -join $LF
Invoke-RestMethod -Uri $Uri -Method Post -ContentType "multipart/form-data; boundary=`"$boundary`"" -Headers $Headers -Body $bodyLines
On Serverside I get
Servlet.service() for servlet [dispatcherServlet] in context with path [/...] threw exception [Request processing failed; nested exception is
org.springframework.web.multipart.MultipartException: Failed to parse multipart servlet request;
nested exception is java.io.IOException: org.apache.tomcat.util.http.fileupload.FileUploadException:
Header section has more than 10240 bytes (maybe it is not properly terminated)] with root cause
org.apache.tomcat.util.http.fileupload.MultipartStream$MalformedStreamException: Header section has more than 10240 bytes (maybe it is not properly terminated)at
org.apache.tomcat.util.http.fileupload.MultipartStream.readHeaders(MultipartStream.java:523)
~[tomcat-embed-core-8.5.34.jar!/:8.5.34]at org.apache.tomcat.util.http.fileupload.FileUploadBase$FileItemIteratorImpl.findNextItem(FileUploadBase.java:880)
~[tomcat-embed-core-8.5.34.jar!/:8.5.34]at org.apache.tomcat.util.http.fileupload.FileUploadBase$FileItemIteratorImpl.<init>(FileUploadBase.java:845)
I need to execute it on a windows machine where I do not haver curl unfortunately.
Appreciate any help