Required request part 'config' is not present node-fetch - node.js

I'm trying to convert this curl command to a node fetch request.
curl -X POST http://localhost:7200/test -H 'Content-Type: multipart/form-data' -F "config=#test.ttl"
What I have so far sends the file as formdata via a POST request, just like the curl request. However, I am not sure how to include the config=#test.ttl in the request. I tried adding it to a headers object and I got back invalid characters errors so I am not sure where to put it. When I run the request the way it is below. I get back 'Required request part 'config' is not present' so it is definitely required to put the config somewhere.
const fetch = require("node-fetch");
const FormData = require('form-data');
const form = new FormData();
form.append('test.ttl', 1);
fetch('http://localhost:7200/test', {
method: 'POST',
body: form
})
.then(res => res.json())
.then(json => console.log(json));
Thanks

Thanks #bato3!
Creating a readStream for the data in the file worked. Posting the working code below if anyone wants to reference it in the future.
const fetch = require("node-fetch");
const fs = require('fs');
const FormData = require('form-data');
const form = new FormData();
form.append('config', fs.createReadStream('test.ttl'));
fetch('http://localhost:7200/test', {
method: 'POST',
body: form
})
.then(res => res.text())
.then(body => console.log(body));

Related

Axios : send image with FormData on Prestashop API

I'm trying to upload on image on the Prestashop API with form-data/axios.
For that, i just need to send a post request with the images joined in an "image" parameter.
I did this simple node.js script (mine is much more complicated but i simplified for here):
const FormData = require("form-data");
const fs = require("fs");
const axios = require("axios");
// Read the image file into a buffer
const imageBuffer = fs.readFileSync("image.jpg");
// Create a FormData object
const form = new FormData();
// Append the image buffer to the form data
form.append("image", imageBuffer);
// Make an HTTP POST request to the PrestaShop API
axios({
method: "POST",
url: "https://XXX/api/images/products/15924",
data: form, // set the request body using the data field
params: {
ws_key: "XXX",
},
headers: {
"Content-Type": "multipart/form-data; boundary=" + form.getBoundary(),
},
})
.then((response) => {
console.log(response);
})
.catch((error) => {
console.error(error.response.data);
});
But i get this answer:
<message><![CDATA[Please set an "image" parameter with image data for value]]></message>
I tried a LOT of things. With fs.createReadStream instead of formData, with http instead of axios, with a buffer or a file, etc ... and i alway end with this error.
I would be glad if someone has an idea :-)
Thx !
I finally succeed!
Two changed were needed:
Adding the filename in the append (thanks Dmitriy Mozgovoy for pointing that out in the comment)
Adding the size in the headers with "Content-Length": formData.getLengthSync()
Without these 2 missing elements, it seems that PHP received an empty $_FILES variable.
Final version:
const FormData = require("form-data");
const fs = require("fs");
const axios = require("axios");
// Read the image file into a buffer
const imageBuffer = fs.readFileSync("image.jpg");
// Create a FormData object
const form = new FormData();
// Append the image buffer to the form data
form.append("image", imageBuffer, "image.jpg");
// Make an HTTP POST request to the PrestaShop API
axios
.post("https://example.com/api/images/products/15924", form, {
params: {
ws_key: "EXAMPLE",
},
headers: {
...form.getHeaders(),
"Content-Length": form.getLengthSync(),
},
})
.then((response) => {
console.log(response);
})
.catch((error) => {
console.error(error.response.data);
});

How to send png file as binary data to node.js server from react?

I am working with an api that requires me to send png files as binary data to my backend. In their docs they show how to do this with a curl example ( I have never used curl ) but they dont show how to do this with axios to a node.js server ( despite examples of node.js on everything else).
How would I convert this following example of a curl to post request to a node.js server?
I am using axios and react for the front end and Node.js for backend.
Here is the curl example, How would I do this in axios?
Also, How do I convert a .png file to binary data in React before sending post request with axios?
curl -u "<account_sid>:<account_secret>" --data-binary #<filename.png> -H "Content-Type: <content-type of upload>" https://mcs.us1.twilio.com/v1/Services/<chat_service_sid>/Media
You can convert your cURL requests with this utility: https://kigiri.github.io/fetch/
Yours in particular will look like this, and fetch and axios are nearly identical:
fetch("https://mcs.us1.twilio.com/v1/Services//Media", {
body: "#<filename.png>",
headers: {
Authorization: "Basic PGFjY291bnRfc2lkPjo8YWNjb3VudF9zZWNyZXQ+",
"Content-Type": "<content-type of upload>"
},
method: "POST"
})
You can read this article here.
By MDN https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/Sending_and_Receiving_Binary_Data
const axios = require('axios');
const FormData = require('form-data');
const fs = require('fs/promises');
// Read image from disk as a Buffer
const image = await fs.readFile('./stickers.jpg');
// Create a form and append image with additional fields
const form = new FormData();
form.append('productName', 'Node.js Stickers');
form.append('productDescription', 'Cool collection of Node.js stickers for your laptop.');
form.append('productImage', image, 'stickers.jpg');
// Send form data with axios
const response = await axios.post('https://example.com', form, {
headers: {
...form.getHeaders(),
Authentication: 'Bearer ...',
},
});
You can convert any curl into httpRequest using
https://curlconverter.com/#javascript
and read about curl information from
https://everything.curl.dev/http/post
for your curl
curl -u "<account_sid>:<account_secret>" --data-binary #<filename.png> -H "Content-Type: " https://mcs.us1.twilio.com/v1/Services/<chat_service_sid>/Media
`fetch('https://mcs.us1.twilio.com/v1/Services/<chat_service_sid>/Media', {
method: 'POST',
headers: {
'Content-Type': '<content-type of upload>',
'Authorization': 'Basic ' + btoa('<account_sid>:<account_secret>')
},
body: '<filename.png>'
});`
You can try to use FileReader to read the given file as binary and send it using fetch/axios.
Second, the curl's -u "<account_sid>:<account_secret>" sends Authorization header. You can simply use btoa(username + ':' + 'password') to achieve that.
Here's an example using fetch and FileReader.
import React, {useState} from 'react';
function FileUploadComponent(){
const [selectedFile, setSelectedFile] = useState();
const changeHandler = (event) => {
setSelectedFile(event.target.files[0]);
};
const handleSubmission = () => {
const reader = new FileReader();
reader.onload = (event) => {
const url = 'https://mcs.us1.twilio.com/v1/Services/<chat_service_sid>/Media';
const headers = {
Authorization: "Basic " + btoa(username + ":" + password),
'Content-Type': selectedFile.type
}
fetch(url, { method: 'POST', body: event.target.result, headers })
.then((response) => response.json())
.then((result) => {
console.log('Success:', result);
})
.catch((error) => {
console.error('Error:', error);
});
};
reader.readAsBinaryString(selectedFile)
};
return (
<div>
<input type="file" name="file" onChange={changeHandler}/>
<div>
<button onClick={handleSubmission}>Submit</button>
</div>
</div>
)
}
Here's some useful links:
https://tr.javascript.info/fetch-basics#submit-an-image
https://developer.mozilla.org/en-US/docs/Web/API/FileReader/readAsBinaryString

How to upload file using axios post request

I am trying to upload a file to url using axios post request. But i am getting 500 internal server error.
If the same request I tried from postman file gets uploaded with 200 status code.
I am not sure what should be the content-Type here.
here is my code.
const axios = require('axios')
var FormData = require('form-data');
var fs = require("fs");
var request = require('request');
const formData = {
file: fs.createReadStream('myfile.txt')
}
const config = {
headers: {
'Content-Type': 'multipart/form-data'
}
};
axios.post('myurl',formData,config)
.then((res) => {
console.log(`statusCode: ${res.status}`)
console.log(res.data)
})
.catch((error) => {
console.log(error)
})
Please check your frontend, when you click submit, do you call event.preventDefault();
const formData = {
file: fs.createReadStream('myfile.txt')
}
It's a plain javascript object, not a ready-to-use formData. You just forget to transform it into a real FormData object. Just check for the document of form-data module.
Also it seems that when you post a real FormData, the "Content-type" header is unnecessary as axios will automaticly handle it for you.

How to post form data using Axios in node

EDIT Changing the title so that it might be helpful to others
I am trying to upload an image to imgbb using their api using Axios, but keep getting an error response Empty upload source.
The API docs for imgbb shows the following example:
curl --location --request POST "https://api.imgbb.com/1/upload?key=YOUR_CLIENT_API_KEY" --form "image=R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7"
My node code to replicate this is:
const fs = require('fs')
const FormData = require('form-data')
const Axios = require('axios').default
let file = '/tmp/the-test.png'
let url = 'https://api.imgbb.com/1/upload?key=myapikey'
var bodyData = new FormData();
let b = fs.readFileSync(file, {encoding: 'base64'})
bodyData.append('image', b)
Axios({
method: 'post',
url: 'url',
headers: {'Content-Type': 'multipart/form-data' },
data: {
image: bodyData
}
}).then((resolve) => {
console.log(resolve.data);
}).catch(error => console.log(error.response.data));
But I keep getting the following error response..
{
status_code: 400,
error: { message: 'Empty upload source.', code: 130, context: 'Exception' },
status_txt: 'Bad Request'
}
Not sure exactly where I am failing.
For the sake of completion and for others, how does the --location flag translate to an axios request?
The issue was in the headers. When using form-data, you have to make sure to pass the headers generated by it to Axios. Answer was found here
headers: bodyData.getHeaders()
Working code is:
const fs = require('fs');
const FormData = require('form-data');
const Axios = require('axios').default;
let file = '/tmp/the-test.png';
var bodyData = new FormData();
let b = fs.readFileSync(file, { encoding: 'base64' });
bodyData.append('image', b);
Axios({
method : 'post',
url : 'https://api.imgbb.com/1/upload?key=myapikey',
headers : bodyData.getHeaders(),
data : bodyData
})
.then((resolve) => {
console.log(resolve.data);
})
.catch((error) => console.log(error.response.data));

What is the axios or ajax equivalent for cURL's --form?

I am creating a task to send a PUT request and upload a .pot file using axios in node.
I can run
curl -i -u api:<api-key> -F file=#dist/file.pot https://api-link.com/v2/api
and it'll work fine
I have tried doing this in node
var fd = require('form-data');
var axios = require('axios');
var form = new FormData();
form.append('file', 'dist/file.pot');
var header = { headers: Object.assign({}, apiToken(), form.getHeaders()) };
axios.put('https://api-link.com/v2/api/', form, header)
.then(function(res) {
console.log(res);
})
.catch(function(err) {
console.log(err);
})
and this doesn't work like the curl command. apiToken() is a function to handle the -u api:<api-key> part of the curl command, and it returns {'Authorization': 'Basic <api-key>'}. I've checked that the function works because I am able to successfully do a get request.
So what is the equivalent of -F file=#dist/file.pot in ajax or axios?
Try the below solution:
var options = {
headers: Object.assign({'Content-Type': 'multipart/form-data'}, apiToken(),
form.getHeaders())
};
axios.post('https://api-link.com/v2/api/', formData, options)
Also check if the content-type header is being set as multipart/form-data or not.

Resources