I cannot send base 64 url encoded data to my nodejs backend - node.js

I am trying to send post request to backend containing base64url encoded value of my image. When I send request with any random string, the request is received at backend but when I try to do same thing using encoded value, it responds me back with
request failed with status code 500
My code for the request is:
const uploadFileHandler = async (e) => {
const file = e.target.files[0];
const reader = new FileReader();
reader.readAsDataURL(file);
reader.onloadend = () => {
setPreviewSource(reader.result);
uploadtobackend(reader.result);
};
const uploadtobackend = async (filedata) => {
try {
const config = {
headers: {
'Content-Type': 'application/json',
},
};
console.log(config);
console.log(filedata);
const { data } = await axios.post(
`/api/uploads`,
{
data: filedata,
},
config,
);
setImages(data);
setUploading(false);
} catch (error) {
console.log(error);
setUploading(false);
}
};
};
Here filedata is the encoded value and it is displayed if I console it.
Instead of
data: filedata
If I send
data: "some random string"
then request reaches backend otherwise not.

You nedd to send your file by wrapping in FormData.
You can do something like
const fd = new FormData()
// data you want to send other than file
fd.append('payload',JSON.stringify(payload))
fd.append('file',file) // file you want to send to node backend
Now in your backed you can get this file using req.file

Probably you need to use JSON.stringify() here are some example of use
const { data } = await axios.post(
`/api/uploads`,
{
data: new Buffer(JSON.stringify(filedata)).toString("base64")
},
config
)

Related

Convert buffer to readStream

I have endpoint which is receiving files and need to send these files to 3rd party. However i'm not converting these files properly cuz i receive Invalid request format but if i read the file from fs the file is successfully deployed. How to create readStream from the input file? I tried Readable.from(file.buffer) still error. If i pass createReadStream(join(process.cwd(), 'images...')) is working as expected, here is the script.
export const deployFile = async (
file: Express.Multer.File,
httpService: HttpService,
): Promise<string> => {
const formData = new FormData();
// Working
// formData.append('file', createReadStream(join(process.cwd(), '/images/1.jpeg')));
// Not working
formData.append('file', Readable.from(file.buffer));
try {
const observable = httpService
.post(process.env.PINATA_BASE_URL + '/pinning/pinFileToIPFS', formData, {
headers: {
'Content-Type': `multipart/form-data; boundary=${formData.getBoundary()}`,
pinata_api_key: process.env.PINATA_API_KEY,
pinata_secret_api_key: process.env.PINATA_API_SECRET_KEY,
},
})
.pipe(map((response) => response.data));
const response = await lastValueFrom(observable);
return response.IpfsHash;
} catch (error) {
logger.error(`Error deploying image reason: ${error.response.data.error}`);
}
};

Azure speech to text in react-native wav file pass issue

I want use Azure's STT REST API for my react-native app with recorded audio.
But I've try to search how to pass the wav file but always response "No audio data received" or other error response.
I'm very sure the subscribe key is working cause when I use get token it responses 200.
And the wav file is not the problem,either.Cause when I download the file to my computer then upload it in Azure STT's homepage,it responses the correct answer.
The last,I've tried to figure out how to pass it in right form,but every things are for website.
Here's my code
`
const file = new ReactNativeFile({
uri:
`file://${audioFile}`,
type: 'audio/wav',
name: 'ABCS160101e1a011b160a3e169d7b0.wav',
});
let form = new formData();
const headers = {
'Ocp-Apim-Subscription-Key': 'MyKey',
'Content-type': 'audio/wav; codecs=audio/pcm;samplerate=16000',
Accept: 'application/json',
};
const url = `https://eastasia.stt.speech.microsoft.com/speech/recognition/conversation/cognitiveservices/v1?language=en-US`;
await form.append('audio', file);
console.log('before');
let response = await axios.post(url, form, {
headers: headers,
});
console.log('after');
console.log('result', JSON.stringify(response));
} catch (err) {
getlog.cw('err23', err);
return err;
}
};`
and Here's My recording function in another place,it's working for play.
import AudioRecord from 'react-native-audio-record';
const options = {
sampleRate: 16000, // default 44100
bitsPerSample: 16, // 8 or 16, default 16,
wavFile: "ABCS160101e1a011b160a3e169d7b0.wav"
};
const toggleRecord = async () => {
if (isRecording) {
const audioFile = await AudioRecord.stop();
setIsRecording(false);
// reloadRecorder();
} else {
setIsRecording(true);
AudioRecord.init(options);
AudioRecord.start();
}
};
Firstly, write
let form = new FormData();
Instead of
let form = new formData();
Secondly, I suppose you audioFile looks like this - file://.... So you dont have to write like this uri: file://${audioFile} ..You can simply write
uri:audioFile
SO final implementation would be
let form = new FormData();
form.append('audio', {
uri: audioFile,
type: 'audio/wav',
name: 'ABCS160101e1a011b160a3e169d7b0.wav',
});
const headers = {
'Ocp-Apim-Subscription-Key': 'MyKey',
'Content-type': 'audio/wav; codecs=audio/pcm;samplerate=16000',
Accept: 'application/json',
};
const url = `https://eastasia.stt.speech.microsoft.com/speech/recognition/conversation/cognitiveservices/v1?language=en-US`;
console.log('before');
let response = await axios.post(url, form, {
headers: headers,
});
console.log('after');
console.log('result', JSON.stringify(response));

IPFS Pinata service not accepting file

I have a code as shown below that uploads files from the browser and saves in the server, once it has been saved to the server, I want the server to connect to the Pinata API so the file can also be saved to the IPFS node.
let data = new FormData();
const fileBuffer = Buffer.from(`./public/files/${fileName}`, 'utf-8');
data.append('file', fileBuffer, `${fileName}`);
axios.post('https://api.pinata.cloud/pinning/pinJSONToIPFS',
data,
{
headers: {
'Content-Type': `multipart/form-data; boundary= ${data._boundary}`,
'pinata_api_key': pinataApiKey,
'pinata_secret_api_key': pinataSecretApiKey
}
}
).then(function (response) {
console.log("FILE UPLOADED TO IPFS NODE", fileName);
console.log(response);
}).catch(function (error) {
console.log("FILE WASNT UPLOADED TO IPFS NODE", fileName);
console.log(error);
});
The issue i'm having is that after creating a buffer of my file and wrapping it in a formdata, the pinata API returns an error :
data: {
error: 'This API endpoint requires valid JSON, and a JSON content-type'
}
If i convert the data to string like JSON.stringify(data) and change the content-type to application/json, the file buffer will be uploaded successfully as string.
I hope explained it well to get a solution. Thanks.
It looks like you're attempting to upload a file to the pinJSONToIPFS endpoint, which is intended to purely be used for JSON that is passed in via a request body.
In your situation I would recommend using Pinata's pinFileToIPFS endpoint
Here's some example code based on their documentation that may be of help:
//imports needed for this function
const axios = require('axios');
const fs = require('fs');
const FormData = require('form-data');
export const pinFileToIPFS = (pinataApiKey, pinataSecretApiKey) => {
const url = `https://api.pinata.cloud/pinning/pinFileToIPFS`;
//we gather a local file for this example, but any valid readStream source will work here.
let data = new FormData();
data.append('file', fs.createReadStream('./yourfile.png'));
return axios.post(url,
data,
{
maxContentLength: 'Infinity', //this is needed to prevent axios from erroring out with large files
headers: {
'Content-Type': `multipart/form-data; boundary=${data._boundary}`,
'pinata_api_key': pinataApiKey,
'pinata_secret_api_key': pinataSecretApiKey
}
}
).then(function (response) {
//handle response here
}).catch(function (error) {
//handle error here
});
};
The proper code to pin any file to IPFS is as below.
Apparently, even Pinata support staff didn't know this.
You need to set an object with the property name filepath as your last parameter. The name doesn't matter, it can be a duplicate, it can be the same as others, or it can be unique.
const url = "https://api.pinata.cloud/pinning/pinFileToIPFS";
const fileContents = Buffer.from(bytes);
const data = new FormData();
data.append("file", fileContents, {filepath: "anyname"});
const result = await axios
.post(url, data, {
maxContentLength: -1,
headers: {
"Content-Type": `multipart/form-data; boundary=${data._boundary}`,
"pinata_api_key": userApiKey,
"pinata_secret_api_key": userApiSecret,
"path": "somename"
}
});
Code to upload a file on IPFS using Pinata.
There are two methods available to upload files/images on Pinata. One is with Pinata SDK and the second is the pinFileToIPFS endpoint.
If you are uploading files from Next.js then you cannot convert your image into binary using fs.createReadStream or Buffer.from. These packages support the Node side. So if you want to upload the file with Next.js on Pinata then you can use this code.
// convert file into binary
const data = new FormData();
data.append("title", file.name);
data.append("file", file);
const url = "https://api.pinata.cloud/pinning/pinFileToIPFS";
// pass binary data into post request
const result = await axios.post(url, data, {
maxContentLength: -1,
headers: {
"Content-Type": `multipart/form-data; boundary=${data._boundary}`,
pinata_api_key: "your_pinata_key",
pinata_secret_api_key:
"your_pinata_secret",
path: "somename",
},
});
console.log("RESULT", result);
this will upload a file to ipfs under the path ipfs://{cid}/images/{fileId}
const PINATA_BASE_URL = "https://api.pinata.cloud";
const PINATA_PIN_URI = "/pinning/pinFileToIPFS";
const fileExt = file.type.split("/")[1];
let nftId = 1
// creates a 64byte string '0000...0001' to follow ERC-1155 standard
const paddedId = createPaddedHex(nftId);
const ipfsFileId = `${paddedId}.${fileExt}`;
const ipfsImageFilePath = `/images/${ipfsFileId}`;
const fileUploadData = new FormData();
// this uploads the file and renames the uploaded file to the path created above
fileUploadData.append("file", file, ipfsImageFilePath);
fileUploadData.append(
"pinataOptions",
'{"cidVersion": 1, "wrapWithDirectory": true}'
);
fileUploadData.append(
"pinataMetadata",
`{"name": "${ipfsImageFilePath}", "keyvalues": {"company": "Pinata"}}`
);
const pinataUploadRes = await axios.post(
PINATA_BASE_URL + PINATA_PIN_URI,
fileUploadData,
{
headers: {
Authorization: `Bearer ${PINATA_JWT}`,
},
}
);
const ipfsCID = pinataUploadRes.data.IpfsHash;

Usestate hook is not working inside onChange Handler

I am trying to send my image data as base64url encoded form to the backend. I am able to get the base64 URL encoded value in my frontend but as I try to set it to something using useState hooks, I am facing issues. The value is not being set. My code is-
const uploadFileHandler = async (e) => {
const file = e.target.files[0]
const reader = new FileReader()
reader.readAsDataURL(file)
reader.onloadend = () => {
console.log('reader result is-')
console.log(reader.result)
setPreviewSource(reader.result)
console.log('preview source value is-')
console.log(previewSource)
}
try {
console.log('reader result is-')
console.log(reader.result)
const imagedata = JSON.stringify(reader.result)
await fetch('/api/uploads', {
method: 'POST',
body: JSON.stringify({
data: previewSource,
}),
headers: {
'Content-Type': 'application/json',
},
})
} catch (error) {
console.error(error)
setUploading(false)
}
}
As I consoled some values, I am getting values of console.log(reader.result) but If I set it to setPreviewSource(reader.result) it displays nothing but I am able to get the previewSource value inside my return .
enter image description here
So, how can I get value inside previewSource so that I can send it to
backend
.

gnupg encryption using nodejs

what is the better library to use gnupg encryption using nodejs
I have a binary public key,
Need to encrypt json payload,
Send it as a formdata (multipart-form) to another API.
I tried looking at openpgp.js, tried reading the key and encrypting, but no luck.
Appreciate any help
a binary public key was given to me along this article to encrypt and send a json payload.
https://www.ibm.com/support/knowledgecenter/SS4T5W/Watson_Talent_Data_Management_Administrator_Guide/gnupg_to_import_pgp_keys.html
I need to do this in nodejs..
I've used openpgp, form-data, stream for posting this as a formdata to api.
below is the code I've tried.
// encrypting the json payload. Is there anything I'm doing wrong here? receiving end is always failing to decrypt, always the response is a bad request
const pgpEncrypt = async (payload) => {
var encryptedKey = await fs.readFileSync("pub.bpg");
const keys = (await openpgp.key.read(encryptedKey)).keys;
const data = await openpgp.encrypt({
message: openpgp.message.fromText(JSON.stringify(payload, null, 0)),
publicKeys: keys,
armor: false,
});
return data.message.packets.write();
};
const formData = new FormData();
let fileContent = await pgpEncrypt(customPayload);
let stream = bufferToStream(Buffer.from(fileContent));
formData.append("file", stream);
const { Readable } = require("stream");
function bufferToStream(binary) {
const readableInstanceStream = new Readable({
read() {
this.push(binary);
this.push(null);
},
});
return readableInstanceStream;
}
axios.post(url, formData, {
headers: {
...formData.getHeaders(),
Authorization: `Bearer ${accessToken}`,
},
})
);

Resources