I am uploading multiple file(s) using a file reader
My aim is to get the base64 data of every files as array and output to console. But my code is always displaying empty array due to async
How can I display the base64 array when all filereaders are completely read?
My code is here
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script>
<script>
var file;
var allfiles = [];
function uploadForm() {
Object.keys($('#file')[0].files).forEach(function(f){
reader = new FileReader()
console.log("---------")
reader.readAsDataURL( $('#file')[0].files[f]);
reader.onloadend = function(e) {
allfiles.push(e.target.result);
showMessage("Uploaded")
};
});
console.log(JSON.stringify(allfiles))
showMessage('Uploading file..<img width="20px;" src="https://c.tenor.com/XK37GfbV0g8AAAAi/loading-cargando.gif"/>');
}
/* Object.keys(files).forEach(function(f){
alert(files[f])
reader.readAsDataURL(files[f]);
})*/
function showMessage(e) {
$('#progress').html(e);
$('#file').val('');
}
</script>
<table cellpadding="5px">
<tr>
<td>Select File:</td>
<td>
<input id="file" type="file" value="" accept=".csv,.xlsx,.docx,.rtf,.pdf,.pptx,.txt" multiple>
</td>
</tr>
<tr>
<td colspan="2"><button onclick="uploadForm(); return false;">Upload</button> </td>
</tr>
<tr>
<td colspan="2">
<div id="progress"></div>
</td>
</tr>
</table>
CodePudding user response:
In your specific case, readAsDataURL
is completing before reader.onloadend
gets assigned a listener. Reordering will solve it:
reader.onloadend = function(e) {
allfiles.push(e.target.result);
showMessage("Uploaded")
};
reader.readAsDataURL( $('#file')[0].files[f]);
But this will not work for larger files (when readAsDataURL
behaves async
). I will suggest you start using Promises
:
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script>
<script>
var file;
var allfiles = [];
function loadFile(file) {
return new Promise((resolve, reject) => {
const reader = new FileReader()
console.log("---------")
reader.onerror = reject;
reader.onload = (e) => resolve(e.target.result);
reader.readAsDataURL(file);
})
}
function filesToArray(files) {
const out = [];
for (let i = 0; i < files.length; i) out.push(files[i]);
return out;
}
function uploadForm() {
const files = filesToArray($('#file')[0].files);
let uploaded = 0;
const promises = files.map(async f => {
const result = await loadFile(f);
showMessage(`${uploaded }/${files.length}`);
allfiles.push(result);
});
showMessage('Uploading file..<img width="20px;" src="https://c.tenor.com/XK37GfbV0g8AAAAi/loading-cargando.gif"/>');
Promise.all(promises)
.then(r => {
console.log(allfiles);
showMessage('Uploaded');
})
.catch(e => showMessage('Failed'));
}
function showMessage(e) {
$('#progress').html(e);
$('#file').val('');
}
</script>
<table cellpadding="5px">
<tr>
<td>Select File:</td>
<td>
<input id="file" type="file" value="" accept=".csv,.xlsx,.docx,.rtf,.pdf,.pptx,.txt" multiple>
</td>
</tr>
<tr>
<td colspan="2"><button onclick="uploadForm(); return false;">Upload</button> </td>
</tr>
<tr>
<td colspan="2">
<div id="progress"></div>
</td>
</tr>
</table>