2

I am attempting to add Base64 encoded images to a string array. Using a file input form created with react-bootstrap's FormControl:

<FormControl
   type="file"
   values={this.state.files}
   multiple
   onChange={this.addImage.bind(this)}
/>

I am calling this function:

addImage(event) {
  var newArr = [];
  for(var i=0; i<event.target.files.length; i++) {
    newArr.push(this.getBase64(event.target.files[i])));
  }
  this.setState({ files: newArr });
}

The function which encodes the images looks like this:

getBase64(file) {
  var reader = new FileReader();
  reader.onloadend = function() {
    return reader.result
  }
  reader.readAsDataURL(file);
}

When the addImage() function calls the getBase64() function the returned value is undefined. I believe this is caused from the time it takes the getBase64() function to run. When I add a console.log line to spit out the reader.result the base64 string is output to the console properly, but the returned value is still, obviously, the same.

What is going on here and how can I get the actual base64 string returned properly?

Spicy Null
  • 37
  • 1
  • 7

1 Answers1

2

No value is returned from getBase64 function synchronously from within an event handler which provides results asynchronously. FileReader loadend event returns results asynchronously. You can use Promise.all() or async/await to get value returned asynchronously from getBase64() function call

class ReadFiles {
  constructor() {}
  async addImage(event) {
    const newArr = [];
    for (let i = 0; i < event.target.files.length; i++) {
      newArr.push(
        await this.getBase64(event.target.files[i])
      );
    }
    const o = {
      files: newArr
    };

    console.log(o);
  }

  getBase64(file) {
    return new Promise(function(resolve) {
      var reader = new FileReader();
      reader.onloadend = function() {
        resolve(reader.result)
      }
      reader.readAsDataURL(file);
    })
  }

}

let reader = new ReadFiles();

document.querySelector("input[type=file]")
.onchange = e => reader.addImage.call(reader, e);
<input type="file" multiple>
guest271314
  • 1
  • 15
  • 104
  • 177