POST multipart/form-data with file data from URL using javascript? - javascript

I'm trying to call an API using javascript that contains a file in the POST request. The file is located at another URL that I have to grab before calling the API. I think I need to use a fetch to get the file data as a blob and then pass it along to the post request.
I have a working example in CURL but can't work out the syntax to translate it into JS.
Working example in CURL:
curl -X POST -H 'Authorization: Token token=****' -H 'Content-Type: multipart/form-data'
-H 'content-type: multipart/form-data; boundary=----WebKitFormBoundary7MA4YWxkTrZu0gW' -F file=#/User/somefile.pdf -F file_name=nameForFile
-F is_shared=true -F targetable_id=1 -F targetable_type=Lead -X POST "https://endpoint.com/api/documents"
Javascript:
var formData = new FormData();
fetch("http://wheremyfileis.com/file.pdf")
.then(response => response.blob())
.then(fileData => {
var fileBlob = new Blob((fileData );
formData.append("targetable_id", 1);
formData.append("targetable_type", "Lead");
formData.append("file", fileBlob);
var headers = {"Authorization": "Token token=***", "Content-Type":"multipart/form-data"};
var options = { headers: headers, body: "Hello world"};
var url = "https://endpoint.com/api/documents";
client.request.post(url, options)
.then (
function(data) { console.log(data); },
function(error) {console.log(error);}
);

Related

Trouble with Chainlink External Adapter making an API call to Spotify

I made an external adapter from the Javascript External Adapter Template from Chainlink, trying to use the Client Credentials flow for Spotify's API to return artist data, documentation listed below.
https://developer.spotify.com/documentation/general/guides/authorization-guide/#client-credentials-flow
https://developer.spotify.com/console/get-artist/
and I am able to make the call just fine with this code through Axios
but when I try to run the same call through the External Adapter which uses Axios for it's API calls as well, I get this error.
Here is a snippet of the main code of the external adapter from index.js
const customParams = {
artist: [''],
endpoint: false
}
const createRequest = (input, callback) => {
// The Validator helps you validate the Chainlink request data
const apiID = process.env.API_ID
const apiKey = process.env.API_KEY
let token = 'BQDlkzka093OuR4tL7XyaI-Tag4R166FQGBSogBP6hEBxhsCjH8XfMRqs_apKFk0T87FGIrwPtT1bkuGCeE';
const validator = new Validator(callback, input, customParams)
const jobRunID = validator.validated.id
const endpoint = validator.validated.data.endpoint
const artistID = validator.validated.data.artist.toUpperCase()
const url = `https://api.spotify.com/v1/artists/${artistID}`
const params = {
artistID
}
// curl -X "GET" "https://api.spotify.com/v1/artists/5K4W6rqBFWDnAN6FQUkS6x" -H "Accept: application/json" -H "Content-Type: application/json" -H "Authorization: Bearer authtoken"
// This is where you would add method and headers
// you can add method like GET or POST and add it to the config
// The default is GET requests
// method = 'get'
// headers = 'headers.....'
const head = {
'Accept' : 'application/json',
'Content-Type' : 'application/json',
'Authorization' : 'Bearer ' + token
}
const config = {
url,
headers: head
}
console.log("config:", config)
and this is the command I am running in the terminal to pass in the Spotify Artist ID
curl -X POST -H "content-type:application/json" "http://localhost:8080/" --data '{ "id": 0, "data": { "": "5K4W6rqBFWDnAN6FQUkS6x"} }'
-Edit-
Just to show that the code isn't all totally wrong, I am able to make a call through the external adapter to this url https://jsonplaceholder.typicode.com/posts/5, passing in the 5 with this command.
curl -X POST -H "content-type:application/json" "http://localhost:8080/" --data '{ "id": 0, "data": { "": "5"} }'
The issue was with this line, making the artist ID all uppercase.
const artistID = validator.validated.data.artist.toUpperCase() // Changed this
const artistID = validator.validated.data.artist // To this

Can't upload video through Imgur API with javascript on client

I have a problem with using Imgur API. I received clientId for anon uploading of media files. Then I tried to use this credentials for API requests. I had problems with using 'https://api.imgur.com/3/upload' route for uploading from the client browser Javascript, but then I found that 'https://api.imgur.com/3/image' works as expected with images uploading (in base64 format), but not working as expected with video uploading (in binary format, because of base64 returns error), after changing method of sending video in binary format doing few requests I managed to receive 200 response code, but the only info I received (besides status info) was 'ticket' field, and nothing else (no error message or code). And I don't know how to use this info to get access to the uploaded video. This type of response not documented anywhere and I'm not really sure it should be working like it is now. Can you please help me with this case? Maybe someone had a similar situation. I have attached 'har' request info from Chrome so that you could see how I made a request, maybe I did mistake somewhere. Really waiting for your answer, thanks!
HAR request info
Send file function:
sendFile = async (fileObj) => {
const myHeaders = new Headers();
myHeaders.append('Authorization', uploadCredentials);
const formData = new FormData(),
{
type
} = fileObj,
fileTitle = fileObj.file.name.split('.').shift(),
splitDataMarker = ';base64,';
let fileData;
if (type === 'image') {
const indexOfMarker = fileObj.data.indexOf(splitDataMarker),
indexOfDataStart = indexOfMarker ? indexOfMarker + splitDataMarker.length : 0;
fileData = fileObj.data.substr(indexOfDataStart);
formData.append('type', 'base64');
} else if (type === 'video') {
formData.append('type', 'file');
const res = await fetch(fileObj.data);
fileData = await res.blob();
}
formData.append(type, fileData);
formData.append('name', fileObj.file.name);
formData.append('title', fileTitle);
const requestOptions: any = {
method: 'POST',
headers: myHeaders,
body: formData,
redirect: 'follow',
};
try {
const res = await fetch(uploadUrl, requestOptions),
data = await res.json();
return data;
} catch (error) {
throw Error(error);
}
},
Your question is answered here: https://stackoverflow.com/a/57240243
In short: for videos you need to use the /upload api endpoint and include a file with a name of video.
If you are including the file as a base64 encoded value in the POST body then you need to set the type to base64, if it is attached, then you need to set the type to file:
# If base64 body data:
curl --location --request POST 'https://api.imgur.com/3/upload' --header 'Authorization: Client-ID 3a49f81624b9a16' --data 'image=R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7&type=base64&disable_audio=0'
CLIENT_ID=3a49f81624b9a16; curl --location --request POST 'https://api.imgur.com/3/upload' --header "Authorization: Client-ID $CLIENT_ID" --data 'image=R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7&type=base64&disable_audio=0'
# If reading file (in this case, from stdin:
echo 'R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7' | base64 --decode | curl --location --request POST 'https://api.imgur.com/3/upload' --header "Authorization: Client-ID $CLIENT_ID" -F 'type=file' -F 'disable_audio=0' -F 'image=#-'
In both examples above, for a video, change image= to video=

Replicate curl with fetch function in js

I have an application that returns a buffer with a Http request. When I run curl in my terminal I get a proper response:
Curl:
curl -s -X GET \ "url" \ -H "authorization: Bearer token" \ -H "content-type: application/json"
Response:
Pendiente now has [{"Key":"73ef53d2848708ae3288db3afb69ee85a663eba2ab147e83494f65585d171a2d","Record":{"cantidad":"100","docType":"fabricacion","estado":"Pendiente","id":"73ef53d2848708ae3288db3afb69ee85a663eba2ab147e83494f65585d171a2d","mercado":"dercadona","owner":"jose","producto":"manzanas","usuario":"jose"}},{"Key":"9b2d52becf9620971c7fd31c54b817533157cb2c7186dd3835f4c502742418b5","Record":{"cantidad":"200","docType":"fabricacion","estado":"Pendiente","id":"9b2d52becf9620971c7fd31c54b817533157cb2c7186dd3835f4c502742418b5","mercado":"mercadona","owner":"jose","producto":"peras","usuario":"jose"}}] after the move
I am trying to get the json part from that response with fetch using js (the fetch goes inside another fetch). I've tried different methods but I can't manage to get it properly
return fetch(url_get_tx,{
method: 'get',
headers: {
'Content-type': 'multipart/form-data',
'authorization': 'Bearer '+data.token
}
}
.then(function(data) {
var reader = data.body.getReader();
return reader.read()
console.log("here");
console.log(typeof(reader));
console.log(reader);
})
Many thanks
return fetch(url_get_tx,{
method: 'get',
headers: {
'Content-type': 'application/json'
'authorization': 'Bearer '+data.token
}
})
.then(function(data) {
return data.json()
}).then(result => console.log(result))

how to send null object (image) using axios to django

I have a django backend that will save / remove image when receiving request from API. I have succesfully delete the saved image if i using swagger / postman to call the API (sending the parameter null object). But i can't get it work via Axios.
The CURL from Swagger :
curl -X PUT --header 'Content-Type: application/json'
--header 'Accept: application/json'
--header 'Authorization: JWT eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VyX2lkIjoxLCJ1c2VybmFtZSI6IlNZU0FETUlOQFRSRUVTLkhBUlBBLkNPTSIsImV4cCI6MTUxNTAzNTU1MiwidXNlcl9uYW1lIjoiU1lTQURNSU5AVFJFRVMuSEFSUEEuQ09NIiwib3JpZ19pYXQiOjE1MTQ5NDkxMDR9.oz3_2fGKlOCesmU_RmSRJZOifZeFFQO1nwAWzyD6BYc'
-d '{ \
"menu_type": 255, \
"icon": null, \
"login_id": 1 \
}'
My axios sample code :
formData.append('menu_type', 255)
formData.append('login_id', 1)
formData.append('icon', null)
const config = {
headers: {
'content-type': 'application/json'
}
}
return new Promise(resolve => {
axios.put(url + form.menu_uuid + "/", formData, config)
.then(function (response) {
resolve(response);
})
.catch(function (error) {
resolve(error.response);
});
});
My request payload screenshot :
Is there something that i missing that makes this axios request won't work ?
i have succesfully deleted image at the API by using this axios code :
formData.append('icon', null, '')
maybe this answer will be useful for other person..

What am I doing wrong in this Angular HTTP request?

I'm getting an error from dropbox api:
Error in call to API function "files/download": HTTP header "Dropbox-API-Arg": could not decode input as JSON.
let url = 'https://content.dropboxapi.com/2/files/download'
let headers = new Headers({ });
headers.append('Authorization', 'Bearer ...');
headers.append('Dropbox-API-Arg', '/readme.txt');
let options = new RequestOptions({ headers: headers });
this.http
.get(url, options)
.subscribe(this.fileContent)
this is the example they put on their api:
curl -X POST https://content.dropboxapi.com/2/files/download \
--header "Authorization: Bearer <get access token>" \
--header "Dropbox-API-Arg: {\"path\": \"/Homework/math/Prime_Numbers.txt\"}"
I might have gotten the headers wrong in angular I've never used them before.
Edit: path variable is a string equal to a file path. i.e. "readme.txt"
Did a quick google and found this: https://www.dropboxforum.com/t5/API-support/HTTP-header-quot-Dropbox-API-Arg-quot-could-not-decode-input-as/td-p/173822
Essentially the format for the variable path isn't in accordance to what the api expects.
I've added the utility function the link provides:
var charsToEncode = /[\u007f-\uffff]/g;
function http_header_safe_json(v) {
return JSON.stringify(v).replace(charsToEncode,
function(c) {
return '\\u'+('000'+c.charCodeAt(0).toString(16)).slice(-4);
}
);
}
EDIT
Your path variable should look like this:
var path = {
path: '/readme.txt'
};

Categories

Resources