Usestate hook is not working inside onChange Handler - node.js

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
.

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));

I cannot send base 64 url encoded data to my nodejs backend

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
)

How to post an image as a File with Axios after Getting it as an Arraybuffer from an attachment

As a POC I would like to make pictures of my receipts (gas, shop etc) and use a chatbot to send them to my accounting software. My problem has to do with the sending of the collected receipt (an image) to the accounting software using its API.
The first part (getting the attachment) results in an Arraybuffer with an image. I used one of the NodeJS samples for that (nr 15).
const attachment = turnContext.activity.attachments[0];
const url = attachment.contentUrl;
let image;
axios.get(url, { responseType: 'arraybuffer' })
.then((response) => {
if (response.headers['content-type'] === 'application/json') {
response.data = JSON.parse(response.data, (key, value) => {
return value && value.type === 'Buffer' ? Buffer.from(value.data) : value;
});
}
image = response.data;
}
).catch((error) => {
console.log(error);
});
I am struggling with the second part. Posting the image to the accounting software
const requestConfig = {
headers: {
'Authorization': 'Bearer ' + accessToken,
'Content-Type': 'application/x-www-form-urlencoded'
}
};
axios.post(postUrl, image, requestConfig)
.then((response) => { console.log(response); }
).catch((error) => {
console.log(error);
});
};
This results in 400. bad request. Probably the API needs a file and I cannot just send the buffer. I tested with Postman and the request is accepted by using application/x-www-form-urlencoded (by using a locally stored image file).
What is best practice to post an image retrieved in a bufferarray?
I think your comment is right on the money that you need to convert it to a file first. The channel isn't an issue because the file will be stored wherever the bot is hosted. The Attachments Sample actually has this code, which gets you close:
fs.writeFile(localFileName, response.data, (fsError) => {
if (fsError) {
throw fsError;
}
// Send the file
const url = '<yourApiUrl>';
const formData = new FormData();
formData.append('file',fs.createReadStream('<pathToFile>'), { knownLength: fs.statSync('<pathToFile>').size });
const config = {
headers: {
...formData.getHeaders(),
'Content-Length': formData.getLengthSync()
}
};
axios.post(url, forData, { headers });
});
I'm not super confident in the // Send the file section only because I can't test against your API. I got most of the code from here.

Issue uploading an image using axios

I'm trying to send an image to my server using axios with react-native.
For doing this, I'm passing the image data (the base 64 encoded image data) directly to an uploadPicture function which uses axios this way:
const uploadPicture = async (data): Promise<AxiosResponse<string>> => {
const response = publicApi.post(
`${API_URL}/upload`,
{
image: data,
},
{
headers: { 'Content-Type': 'multipart/form-data' },
transformRequest: [transformToFormData],
}
);
return response;
};
const transformToFormData: AxiosTransformer = data => {
const formData = new FormData();
for (const key in data) {
formData.append(key, data[key]);
}
return formData;
};
The issue I face :
I get an internal error, like if my image was not correctly transmitted through my request.
If I'm doing the exact same request using Postman, it works fine, setting the body like this :
Which make me think that the issue doesn't come from my server but from my axios request.
Any idea of what I could be doing wrong ? Am I missing any axios option somewhere ?
I managed to find a solution:
I used the fetch function from javascript instead of axios
I send a file object instead of the data directly
I had to disable the react-native network inspect, otherwise the upload won't work
My working solution below, image being the response of react native image picker:
const file = {
uri: image.uri,
name: image.fileName,
type: image.type,
size: image.fileSize,
slice: () => new Blob(),
};
const body = new FormData();
body.append('image', file);
const response = await fetch(`${API_URL}/upload`, {
method: 'POST',
body,
});

Resources