'Send request on fileReader onload
i am using fileReader for uploading images, when images are done uploading i want to send them to server.
my problem is that when there are more than 1 image it sends multiple requests, because i have for loop. how can i make it work?
for (let file of selectedFiles) {
const fileName = file.name;
const reader = new FileReader();
reader.readAsArrayBuffer(file);
reader.onload = () => {
const image = reader.result as any;
var base64 = btoa(
new Uint8Array(image)
.reduce((data, byte) => data + String.fromCharCode(byte), '')
);
imageArray.push({ fileName: fileName, content: base64 });
console.log(imageArray);
this.service.create(this.finalData).subscribe({
next: data => {
console.log(data);
this.openSnackBar("Success", 'x');
},
error: error => {
console.error('There was an error!', error);
}
})
}
}
Solution 1:[1]
If you're dealing with multiple asynchronous things at once, then you will save yourself a lot of effort by using promises.
Start by writing a function which takes a file and returns a promise that resolves to the data you want.
I'll define FileData here to make it clear how things work out later.
type FileData = {
fileName: string;
content: string; // base64 encoded
};
const getFileData = (file) => {
const fileName = file.name;
const promise = new Promise(
(res, rej) => {
const reader = new FileReader();
reader.readAsArrayBuffer(file);
reader.onload = () => {
const image = reader.result as any;
var base64 = btoa(
new Uint8Array(image)
.reduce((data, byte) => data + String.fromCharCode(byte), '')
);
const data: FileData = { fileName: fileName, content: base64 };
res(data)
};
});
return promise;
};
Then do your loop but use the function to get your data and gather the results into an array.
const promises = [];
for (let file of selectedFiles) {
promises.push(getFileData(promises));
};
Then use Promise.all to run another function once all the promises are resolved and you have the data.
Promise.all(promises).then((dataArray: FileData[]) => {
// Now work with dataArray and upload all the data in the array in one go
});
That said. I'd look at changing the server to support a standard multipart MIME formatted request and then upload the data using FormData instead of converting everything to base64 myself.
const data = new FormData(document.getElementById('myForm');
const responsePromise = fetch('/url', { method: "POST", body: data });
… is a lot less effort than the above! And sends all the same data (just in a different format).
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 |
