How to send HTTP request multipart/form-data Content-Type on Apex Salesforce - rest

I need to recreate this curl post using Apex and I can't find a way to do it.
Seems like Salesforce doesn't support this kind of Content-Type.
curl:
curl -i -X POST \
-H "Content-Type:multipart/form-data" \
-F "message=Images Test" \
-F "login=LOGIN" \
-F "password=PASSWORD" \
-F "to=9999999999" \
-F "image=#\"./20190914_132720.jpg\";type=image/jpeg;filename=\"20190914_132720.jpg\"
Anyone has an example of this on Apex?
Thank you

Related

How do I download a file from a GitHub draft

I am using AppVeyor to set up the CI for a GitHub repository and upload the build artifacts to a draft named CI builds. The file is e.g. located under
https://github.com/an_organisation/a_project/releases/tag/untagged-1111aaaacccc0000dddd/filename.tar.gz
and can be accessed and downloaded from a browser.
Now I would like to access those uploaded artifact from another AppVeyor project (i.e. an appveyor.yml script). I tried without success to download with AppVeyor DownloadFile command, curl, and wget using the following commands
set DOWNLOAD_FILENAME=filename.tar.gz
set DOWNLOAD_ADDRESS=https://github.com/an_organisation/a_project/releases/download/untagged-1111aaaacccc0000dddd/$DOWNLOAD_FILENAME
wget --header "Authorization: token $GH_AUTH_TOKEN" --output-document=$DOWNLOAD_FILENAME $DOWNLOAD_ADDRESS
wget --auth-no-challenge --header "Accept:application/octet-stream" --output-document=$DOWNLOAD_FILENAME "$DOWNLOAD_ADDRESS?access_token:$GH_AUTH_TOKEN"
curl -fsSL -G --user "$APPVEYOR_ACCOUNT_NAME:$GH_AUTH_TOKEN" -o $DOWNLOAD_FILENAME $DOWNLOAD_ADDRESS
curl -fsSL -G -H "Authorization: token $GH_AUTH_TOKEN" -H "Accept: application/octet-stream" -o $DOWNLOAD_FILENAME $DOWNLOAD_ADDRESS
curl -fsSL -G -H "Authorization: token $GH_AUTH_TOKEN" -H "Accept: application/octet-stream" -o $DOWNLOAD_FILENAME https://api.github.com/repos/an_organisation/a_project/releases/download/untagged-1111aaaacccc0000dddd/
Slowly I get a feeling that a file download from a draft via GitHub API or download link is not possible.
What is the correct command to download such a file?
TLDR Use the Get Release asset API with header Accept: application/octet-stream :
curl -OJ -L -H "Accept: application/octet-stream" \
-H "Authorization: Token $YOUR_TOKEN" \
"https://api.github.com/repos/$REPO/releases/assets/$ASSET_ID"
You need to have the assetID. In order to have it you need the releaseID if you have not already this information use GET /repos/:user/:repo/releases :
curl -s -H "Authorization: Token $YOUR_TOKEN" \
"https://api.github.com/repos/$REPO/releases" | jq '.[] | {(.name): .id}'
Then get the assets IDs use GET /repos/:user/:repo/releases/:release_id :
curl -s -H "Authorization: Token $YOUR_TOKEN" \
"https://api.github.com/repos/$REPO/releases/$RELEASE_ID" | \
jq -r '.assets[] | {(.id |tostring): .name}'
Then once you have assetID (maybe you already had it btw) you can finally use GET /repos/:user/:repo/releases/assets/:asset_id with header Accept: application/octet-stream. From the documentation :
To download the asset's binary content, set the Accept header of the
request to application/octet-stream. The API will either redirect the
client to the location, or stream it directly if possible. API clients
should handle both a 200 or 302 response.
The following download the file locally :
curl -OJ -L -H "Accept: application/octet-stream" \
-H "Authorization: Token $YOUR_TOKEN" \
"https://api.github.com/repos/$REPO/releases/assets/$ASSET_ID"

POST request to google cloud storage using Curl

In the following Curl command, content type and content length and access bearer are attached to my bucket URI to upload a file to google cloud storage.
C:\softwares\curl>curl -X POST -H "Content-Type:application/json" \
-H "Content-Length:100" \
-H "Authorization: Bearer <MY_OAUTH2_TOKEN>" \
"https://www.googleapis.com/upload/storage/v1/b/kids-74096.appspot.com/o?uploadType=media&name=newcurl" \
-d '{"text":"something"}'
But I am getting this error:
curl: (92) HTTP/2 stream 1 was not closed cleanly: PROTOCOL_ERROR (err 1)
Make sure to include a Content-Type header, and ensure that your Content-Length matches the length of the data you're sending. Here's an example:
curl -k -v -X POST \
-H "Authorization: Bearer <your_oauth2_token>" -H "Content-Length: 8" \
-H "Content-Type: text/plain" \
'https://www.googleapis.com/upload/storage/v1/b/your-bucket/o?uploadType=media&name=yourobjectname' \
-d 'yourdata'
As suggested in the comments, you might find it easier to use gsutil or the Cloud Storage client libraries to accomplish this.

How to upload HttpEntity.Chunked with Multipart.FormData with Akka-Http Client

When trying to upload a large file to a server as chunked entity in Multipart Form:
val chunked = HttpEntity.Chunked.fromData(mimeType, sourceOfByteString)
Multipart.FormData(
Multipart.FormData.BodyPart("downloadPath", HttpEntity(fileResourceRequest.downloadPath.path)),
Multipart.FormData.BodyPart("fileSize", HttpEntity(fileResourceRequest.fileSize.toString)),
Multipart.FormData.BodyPart("data", chunked, Map("filename" → "content"))
).toEntity()
I get this error:
Type mismatch: expected BodyPartEntity, actual HttpEntity.Chunked
When adding a Transfer-Encoding: chunked header manually, Akka-http removes it, as per documentation.
I am able to successfully perform exactly the same Upload using curl
curl -i -X POST \
-H "Content-Type:multipart/form-data" \
-H "Authorization:Bearer BB3F8B79384D08B9F268F21FF76ABFA" \
-H "Transfer-Encoding:chunked" \
-F "downloadPath=/user-data/media/dachi.png" \
-F "fileSize=733830" \
-F "data=#\"./dachi.png\";type=image/png;filename=\"dachi.png\"" \
'http://0.0.0.0:8000'
Use HttpEntity.IndefiniteLength as per documentation:

Post photos to an album using a batch request and curl

I'm trying to post a number of photos to an already created album using cURL with the following command:
curl -F 'access_token=<>' \
-F 'batch=[ \
{"method":"POST","relative_url":"/album_id/photos","url":"<photo_url>"}, \
{"method":"POST","relative_url":"/album_id/photos","url":"<photo_url>"}]' \
https://graph.facebook.com
The error I'm getting is (#324) Requires upload file. Is it even possible to post photos in a batch request to an album and if so what is the correct way to do it with cURL? Thanks!
Edit: the correct command thanks to CBroe is:
curl -F 'access_token=<>' \
-F 'batch=[ \
{"method":"POST","relative_url":"/album_id/photos","body":"url=<photo_url>"}, \
{"method":"POST","relative_url":"/album_id/photos","body":"url=<photo_url>"}]' \
https://graph.facebook.com

watson visual recognition error 400: cannot execute learning task: no classifier name given

I was about to create a new classifier and train the visual recognition with pictures, but I got this error code which is stated in title when I curl following command
curl -u "0xxxxxxxxxxx":"vxxxxxxxxxxxxxx" \
-X POST \
-F "positive_examples=#bottle-positive.zip" \
-F "negative_examples=#bottle-negative.zip" \
-F "name=plasticbottle" \
-k "https://gateway.watsonplatform.net/visual-recognition-beta/api/v2/classifiers?version=2015-12-02"
To set the classifiers you want to use you have to send a JSON containing something like:
{"classifier_ids": ["ClassifierName"]}
So your curl should be something like:
curl -u "username":"pwd" \
-X POST \
-F "images_file=#imagefilename.jpg" \
-F "classifier_ids={\"classifier_ids\":[\"ClassifierName\"]}"
"https://gateway.watsonplatform.net/visual-recognition-beta/api/v2/classify?version=2015-12-02"
I'm not sure what was the problem using V2 api, but now, using V3 API your CURL should look like this example
curl -X POST
-F "apple_positive_examples=#apples1.zip"
-F "banana_positive_examples=#yellow.zip"
-F "orange_positive_example=#pos_ex.zip"
-F "negative_examples=#vegetables.zip"
-F "name=fruit"
"https://gateway-a.watsonplatform.net/visual-recognition/api/v3/classifiers?api_key={api-key}&version=2016-05-20"
So your CURL for bottle should be like
curl -X POST
-F "bottle_positive_examples=#bottle-positive.zip"
-F "negative_examples=#bottle-negative.zip"
-F "name=plasticbottle"
"https://gateway-a.watsonplatform.net/visual-recognition/api/v3/classifiers?api_key={api-key}&version=2016-05-20"
Note that you now should use an api_key to authenticate and no longer a user/pass
This is documented in the v3 doc:
https://www.ibm.com/watson/developercloud/visual-recognition/api/v3/#create_a_classifier