Uploading a file using "fetch" in reactJS - node.js

Uploading a file using "fetch" in reactjs
I am trying to upload a file using ReactJS.
handleUploadfile = (event) => {
event.preventDefault();
const data = new FormData();
data.append('photo',event.target.files[0] );
data.append('name', 'Test Name');
data.append('desc', 'Test description');
fetch("http://localhost:3001/todo/upload", {
method: 'POST',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/x-www-form-urlencoded'
},
body: data
}).then((response) => {
return response.text();
})
}
For some reason I am not able read the files at nodejs(+multer) server using:
req.files
which shows "undefined" at post router.

Finally I found the solution
I had to remove the 'Content-Type' from headers section and it worked out in nodejs using multer.
Using the "multipart/form-data"
'Content-Type': 'multipart/form-data'
requires us to set boundaries and hence it is throwing error at nodejs "Error: Multipart: Boundary not found"
Using the "application/x-www-form-urlencoded"
'Content-Type': 'application/x-www-form-urlencoded'
I am getting the req.body filled but as string but not able to access the individual values.
Hence final solution is removal of 'Content-Type'

Related

Axios returning binary data instead of XML

Been spending the past few hours figuring out why Axios is doing this.
I tried to do this in the request library in nodeJS and it works fine, but Axios isn't.
Essentially what i'm doing is sending a request of XML data:
var options = {
'method': 'POST',
'url': 'https://rvices.svc',
'headers': {
'Content-Type': 'text/xml; charset=utf-8',
'SOAPAction': 'http://etProject'
},
data: xmlData};
with XMLData looking simliar to :
let xmlData = `<?xml version="1.0" encoding="UTF-8"?><soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:com="http://p" xmlns:pws="http://"
etc etc (it has mostly private data in it so I stripped most of it out).
when I try to use axios to get this
const testData = await axios(options)
i get returned a whole lot of code that looks like this:
'���_\x1B�\f�10�\x17�Ч�{O�\x00��5h�S�������\x0F���s�(+Ғ�\x0F�����m�\x15\x01\x13��6b��\x06%\x00��\x15p8<;��W�4����\x0B���\x01���e�\x7FvZ�{���Ï������\x06��-�z��\x01}�!�r�A�\x13��\x11O�w6ũ���{�\x03����;{����\x01\x7Fy��KoՎ���\x1Bߚe��W��mЇ�qD�a��[�7Ӄ���#��F<\x1C/mF�{\x03�h��#�\x16�\x11\x1F\x1F�L9\x0FM\x8A\x0E�\x
17�h���\x03�4�7�f=bj*8�p�\x13_�\x17�5���_�Ӑ�|M>����\r��F�8q�iE�#��\x0E?�v�������O�xq3���x�Q�튱\x1F?G&HG9��6���V\x1B⫯Ev\x01rc\x13\x10�\'�7��`�Ii��x�~LM6�#˒74##�����f�*\x7F\x16(5|\x1CWl��\x07\t\x1F��z�\x15\x00\x1B��4�\x13���LCTG�\x1FI�����\fec�h\x02�~��i`�:Ғ�\x0F���y\b#�]V��g��Ӈ�\x14|���6~\x19~c`�/�O���M\x01��k\x
10�\'+���\x07S\r?|��T�A�\x0FӒ�\x0F��ܷ\'.s�!>�tbX\x05�\fs\x18�\r�"`���\x10lV٠\x05#ܲ�\x02\x0E\x07h���\n' +
'���[�7}�>54 r�����ʦ\x15�\x17��\x0E:
that is the right amount of characters (100k +) but jumbled
compared to doing this with request which returns the xml back I expect ala:
</b:ProjectTaskTypeDetail></b:PwsProjectTaskTypeElement><b:PwsProjectTaskTypeElement><b:ProjectTaskTypeDetail><b:ExternalSystemIdentifier i:nil="true"/><b:ProjectTaskTypeId i:nil="true"/><b:ProjectTaskTypeUid>5776</b:ProjectTaskTypeUid><b:ProjectTaskTypeName>Faon</b:Proj
ectTaskTypeName>
one thing I noticed is axios is breaking my request up into multiple lines like this:
'<com:PwsProjectRef><com:ProjectCode>201268</com:ProjectCode></com:PwsProjectRef>\n' +
'\n' +
'<com:PwsProjectRef><com:ProjectCode>210115-01</com:ProjectCode></com:PwsProjectRef>\n' +
'\n' +
even though there's no \n's in my request or breaks like that.
So i'm wondering if anyone has ran into this before and knows how to solve it?
Request is working but request (from what I can tell?) doesn't work with asynch code (i'm probably wrong about this)
Sorry for the vagueness!
You should be using the responseType config option to set the expected response which reflects the Accept HTTP header and not the Content-Type one:
const options = {
method: 'POST',
url: 'https://rvices.svc',
headers: {
'Content-Type': 'text/xml; charset=utf-8',
'SOAPAction': 'http://etProject'
},
data: xmlData,
responseType: 'document',
responseEncoding: 'utf8'
};
const testData = await axios(options);
The response is being returned in a compressed binary format, but
Axios does not understand the compression format that is being returned from the server. Try forcing the response to a specific compression algorithm like 'deflate' which axios understands. 'gzip' may also work.
The axios 'decompress' option tells axios to automatically decompress the binary data.
var options = {
'method': 'POST',
'url': 'https://rvices.svc',
'headers': {
'Accept-Encoding': 'deflate'
'Content-Type': 'text/xml; charset=utf-8',
'SOAPAction': 'http://etProject'
},
data: xmlData,
decompress: true
};
<!-- end snippet -->
In v1.2.1, it is fixed this error.
try with this code
Save as get-data.js file
const axios = require("axios");
const getData = async () => {
try {
const resp = await axios.get('your xml URL',
{
headers: {
'Accept-Encoding': 'application/xml',
}
}
);
console.log(resp.data);
} catch (err) {
// Handle Error Here
console.error(err);
}
};
getData()
npm install axios
node get-data.js

Upload video to Cloudflare API

I am trying to upload some videos to Cloudflare Stream API. Here is official documentation and its example request using curl: https://developers.cloudflare.com/stream/uploading-videos/upload-video-file/
I am doing the request in Node.js
const uploadVideo = (video: Express.Multer.File): => {
const formData = new URLSearchParams();
formData.append('file', video);
let cloudflareResponse;
try {
cloudflareResponse = await axios.post(
`https://api.cloudflare.com/client/v4/accounts/${ACCOUNT_ID}/stream/copy`,
formData,
{
headers: {
Authorization: `Bearer ${API_KEY}`,
'Content-Type': 'multipart/form-data',
//'Tus-Resumable': '1.0.0',
//'Upload-Length': '600',
//'Upload-Metadata': 'maxDurationSeconds 600'
}
}
);
} catch (e) {
console.log('Error while trying to upload video to Cloudflare API ', e);
}
}
The commented Headers I took from this article, in which the request is done in Django and I tried to replicate it https://medium.com/#berman82312/how-to-setup-cloudflare-stream-direct-creator-uploads-correctly-802c37cbfd0e
The error I am getting is a 400 and here is some of the response
config: {
url: 'https://api.cloudflare.com/client/v4/accounts/...../stream/copy',
method: 'post',
data: 'file=%5Bobject+Object%5D',
headers: {
Accept: 'application/json, text/plain, */*',
'Content-Type': 'multipart/form-data',
Authorization: 'Bearer .....',
'Tus-Resumable': '1.0.0',
'Upload-Length': '600',
'Upload-Metadata': 'maxDurationSeconds 600',
'User-Agent': 'axios/0.21.1',
'Content-Length': 24
},
data: { result: null, success: false, errors: [Array], messages: null }
I am sure something is wrong in the request and hope someone could help me spot the mistake or suggest some modifications that might help. I have been stuck with this problem for hours and on Postman I am also getting a 400 response when trying to send with form-data.

How to send binary data of a file in a request body?

Is there any way to send binary data of a file in body of a put request using nodejs and axios ?
you can use a FormData append your file to it , send it with axios then get it with multer in server side.
const data = new FormData()
data.append('multer_file_name', file, file.name)
axios.post("your_api", data, {
headers: {
accept: 'application/json',
'Accept-Language': 'en-US,en;q=0.8',
'Content-Type': undefined,
},
}).then((response) => {
})
you can get your file like this if you have an input :
const file = document.getElementById('your_input_id').files[0]

How can i pass authroziation token in header with multipart/form-data

I am using reactjs in my front end, so I am converting an image into base64 data and pass it to nodejs, In my backend I am trying send the base64 data to 3rd part API using fetch call, But it returns
401 unauthorization error
If I pass authorization in header nothing happens
const formData = new FormData();
formData.append('file', url);
const resp = await fetch(requestURL, {
method: 'POST',
headers: {
'Authorization': accessToken,
'Content-Type': 'multipart/form-data',
},
body: formData,
});
Can anyone help me with this?

In what format should a fetch POST request be created to access the Imagga API?

I am building a mobile application using React-Native that recommends clothing to users. I am using Imagga's API to get the colors of the clothing while excluding the background. I have tried to make a POST request using fetch from analyzing the node.js code given in the documentation:
image_file_b64 = "" + image_file_b64
//Extracting the colors from the object
let response = await fetch('https://api.imagga.com/v2/colors', {
method: 'POST',
headers: {
'apiKey': '<PLACEHOLDER>',
'apiSecret': '<PLACEHOLDER>',
'Authorization': '<PLACEHOLDER>',
Accept: 'application/json',
'Content-Type': 'application/json',
},
body: JSON.stringify({
image_base64: image_file_b64,
extract_overall_colors: 0,
})
})
let responseJson = await response.json()
console.log(responseJson)
However, the only output that I have received is (what is logged on the last line):
Object {
"status": Object {
"text": "Please provide content for processing.",
"type": "error",
},
}
I've worked with someone from Imagga to solve this issue, but he wasn't familiar with react native. he suggested changing the content-type to "application/x-www-form-urlencoded" or "application/x-www-form-urlencoded;charset=UTF-8", but neither have worked.
I am fairly confident that the problem is from the way that I set up my fetch. If anybody is familiar with the Imagga API, can you please identify what in the code is wrong or the mismatch in formatting between what Imagga expects and what I am giving it that results in it not thinking that I have given it input. Thanks!
the fetch body is not correct, the Content-Type that you use is JSON, why you send the string. modify it as the following, and try it.
let response = await fetch('https://api.imagga.com/v2/colors', {
method: 'POST',
headers: {
'apiKey': '<PLACEHOLDER>',
'apiSecret': '<PLACEHOLDER>',
'Authorization': '<PLACEHOLDER>',
Accept: 'application/json',
'Content-Type': 'application/json',
},
body: {
image_base64: image_file_b64,
extract_overall_colors: 0,
})
})
I read the official API, it gives the node.js example. you can according to it and modify. If the above code is not successful, you can change the content-type to formdata
let params = {
image_base64: image_file_b64,
extract_overall_colors: 0,
};
let formData = new FromData()
formdata.append('RequestData',JSON.stringify(params))
let response = await fetch('https://api.imagga.com/v2/colors', {
method: 'POST',
headers: {
'apiKey': '<PLACEHOLDER>',
'apiSecret': '<PLACEHOLDER>',
'Authorization': '<PLACEHOLDER>',
Accept: 'application/json',
'Content-Type': 'multipart/form-data',
},
body: formData)
})
this is the official api, and you can use postman software to test the request

Resources