1

I tried to load the base64 image string into array by <input type="file"/> I am sure the string is in the array but when I call the array element the console callback is undefined.

as following my code:

fileChange(event){
    if (event.target.files && event.target.files[0]) {
            let imageFiles = [];
            for (var i = 0; i < event.target.files.length; i++) {

              let reader = new FileReader();
              reader.readAsDataURL(event.target.files[i]);
              reader.onload = (e) => {
                  imageFiles[i] = e.target.result;
                  console.log(e.target.result);
              };
            }
            console.log(imageFiles);
            console.log(imageFiles[0]);
        }
  }

//console result:
//"base64 string"
//[]-> 0: "base64 string"
//undefined

I think it because the base64 string is too long, but I have no idea to solve the problem.

It's some ways to solve it?

Champer Wu
  • 1,101
  • 3
  • 13
  • 32
  • 1
    Use `imageFiles[imageFiles.length]` instead of `imageFiles[i]` as `i` is not not going to be captured. Your `console.log(imageFiles[0]);` may occur before `onload()` executes so its value has not been set. – Alex K. Mar 09 '18 at 19:08
  • 1
    If you move those last two console.logs into your `reader.onload` callback, you will probably get a result — reading files is asynchronous, so `console.log(imageFiles)` is currently getting called before the files have finished loading into the variable. – thmsdnnr Mar 09 '18 at 19:09
  • 1
    Possible duplicate of [How do I return the response from an asynchronous call?](https://stackoverflow.com/questions/14220321/how-do-i-return-the-response-from-an-asynchronous-call) – Endless Mar 09 '18 at 19:09
  • Why do you need base64? using [URL.createObjectURL](https://www.google.se/search?q=URL.createObjectURL+mdn&oq=URL.createObjectURL+mdn&aqs=chrome..69i57j0.2603j0j7&sourceid=chrome&ie=UTF-8) is better if you are going to display them and having blob/files is better for uploading. Object url is also synchronous and faster – Endless Mar 09 '18 at 19:10
  • Yes, I find the problem, I console the file in the `reader.onload` function – Champer Wu Mar 09 '18 at 19:32
  • @Endless I want to preview all the select image file in my page – Champer Wu Mar 09 '18 at 19:32
  • 1
    @ChamperWu then use objectURL's – Endless Mar 09 '18 at 19:33
  • @Endless Im reading the doc now, thanks – Champer Wu Mar 09 '18 at 19:35

1 Answers1

1

These two statements

console.log(imageFiles);
console.log(imageFiles[0]);

are called immediately, when reader.onload is not completed yet. Hence, the imageFiles array is empty.

You need to wait until the image is loaded to be able to log it. One way is to use Promises. Here is an example of loading multiple files. Promise.all will wait until all files are loaded and then log them.

document.getElementById("file").addEventListener("change", fileChange);
function fileChange(event) {
    if (event.target.files && event.target.files[0]) {
        console.clear();
        console.log("Loading selected files...");
        let promises = [];
        for (var i = 0; i < event.target.files.length; i++) {
            promises[i] = new Promise(resolve => {
                let reader = new FileReader();
                reader.readAsDataURL(event.target.files[i]);
                reader.onload = (e) => {
                    resolve(e.target.result);
                };
            });
        }      
        Promise.all(promises).then(console.log);
    }
}
<input type="file" id="file" multiple="multiple"/>
Kirill Simonov
  • 8,257
  • 3
  • 18
  • 42