2

I'm trying to use FileReader() in my website but it's returning undefined in the array. This is the first time I'm using the FileReader to send encoded data from my input file. I'm using the API of Recruiterbox and as you can see in the print the encoded_data is undefined. I'm stucked here and need some help. enter image description here

 applyOpening: function applyOpening() {
    let fields = [];
    let formControl = document.querySelectorAll('.form-control');

    for (var i = 0; i < formControl.length; i++) {
      let field = formControl[i];
      let obj = {
        key: field.getAttribute('name')
      }

      if (field.tagName.toLowerCase() === 'input' && field.getAttribute('type') === 'file' ) {
        obj.value = {
          'encoded_data': getBase64(field.files[0]),
          'file_name': field.value
        }
      } else {
        obj.value = field.value
      }
      fields.push(obj);
    }

    function getBase64(file) {
      let reader = new FileReader();

      if (file) {
        return reader.readAsDataURL(file);
      } else {
        return false;
      }
      reader.onloadend = function() {
        return reader.result;
      };
    }

    $.ajax({
      url: 'https://jsapi.recruiterbox.com/v1/openings/' + id + '/apply?client_name=clientname',
      data: JSON.stringify({ fields: fields }),
      dataType: 'json',
      contentType: 'application/json',
      type: 'POST',
      success: function(response) {
        console.log(JSON.stringify(data));
      },
      error: function(er) {
        console.error(er);
      }
    });
  }

Update:

applyOpening: function applyOpening() {

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

    let fields = [];
    let formControl = document.querySelectorAll('.form-control');

    for (var i = 0; i < formControl.length; i++) {

      let field = formControl[i];

      let obj = {
        key: field.getAttribute('name')
      }

      if (field.tagName.toLowerCase() === 'input' && field.getAttribute('type') === 'file' ) {
        if (field.files[0]) {
          getBase64(field.files[0]).then(function(reader) {
              obj.value = {
                'encoded_data': reader.result,
                'file_name': field.value.replace("C:\\fakepath\\", "")
              };
          });
        }
      } else {
        obj.value = field.value;
      }
      if (obj.key !== null) {
        fields.push(obj);
      }
      console.log(obj);
    }

    app.postApplyOpening(fields);

Console log:

console

Request Payload:

request payload

Update 2:

applyOpening: async function applyOpening() {

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

  let fields = [];
  let formControl = document.querySelectorAll('.form-control');

  for (var i = 0; i < formControl.length; i++) {

  let field = formControl[i];

  let obj = {
    key: field.getAttribute('name')
  }

  if (field.tagName.toLowerCase() === 'input' && field.getAttribute('type') === 'file' ) {
    if (field.files[0]) {
      let reader = await getBase64(field.files[0]);
      obj.value = {
        'encoded_data': reader.result.replace(new RegExp("^data:[A-Z]+/[A-Z]+;base64,", "gi"), ''),
        'file_name': field.value.replace("C:\\fakepath\\", "")
      };
    }
  } else {
    obj.value = field.value;
  }
  if (obj.key !== null) {
    fields.push(obj);
  }
  console.log(obj);
}

app.postApplyOpening(fields);
},
codajoao
  • 279
  • 5
  • 16

1 Answers1

4

FileReader returns results asynchronously. Use a promise to get the result asynchronously. You cannot return the result of readAsDataURL, that is undefined, which is what you are seeing.

See here: Javascript base64 encoding function returns undefined

Sean F
  • 4,344
  • 16
  • 30
  • I've edit the question with a updated code. Now in the console log I can see the encoded data but in the request payload I can't see the encoded data. In my response I'm getting this error: ```{"error_message": "Request should be of form {'fields': [{'key': 'candidate_first_name', 'value': 'John'} ...]}"}``` I think this error is coming from the request payload. Any tip? – codajoao May 23 '18 at 15:37
  • It does look like an error with whatever comes from that recruiterbox api. You have fields where fields is array of { key, value } where key is a string and value is { file_name, encoded_data }, file_name is a string and encoded_data is whatever comes out of the file reader. This is not matching what the error is saying you should be sending, which is fields is array of { key, value } where key is a string ('candidate_first_name') and value is a string with the name. – Sean F May 23 '18 at 15:57
  • Click the up arrow if the answer is useful. – Sean F May 23 '18 at 15:59
  • I know that the error is not matching but the problem is about the missing value { file_name, encoded_data } in the request payload. I've updated the code again and now it's working properly. I've removed the promise from ```getBase64``` invoke inside the ```if``` and then assign the ```async``` to the ```applyOpening``` with an ```await``` in the ```getBase64``` invoke function. – codajoao May 23 '18 at 17:21
  • OK, I did not see anything wrong with using the promise .then() construct you had before, but maybe it helps that you now set onloadend before calling into the file reader. – Sean F May 23 '18 at 18:42