1

I am having an issue converting the input file object into Base64 in my ionic v2 app. The issue occurs specifically when using the onload/onloadend reader as it gets called only occasionally (rarest of rarest to be very specific).

I am able to get the file name, size and object when the user clicks on a image file which triggers the attachFile function, but after that when i convert the file object to Base64 using FileReader - onload or onloadend the callback function rarely gets called and the file object is not getting converted to Base64 as a result of this.

File input:

<input #fileInput type="file" accept="image/*" (change)="attachFile($event)">

Attach File:

attachFile(fileInput: any)
{
  let fileList: FileList = fileInput.target.files;

  // I can access the selected file name, size and object correctly without any issues
  console.log("File name = " + fileList[0].name);
  console.log("File size = " + fileList[0].size);
  console.log("File = " + fileList[0]);

  // Converting the file input to base 64 (This rarely works)
  this.convertFileToBase64AndSet(fileList);
}

Base64 Conversion:

convertFileToBase64AndSet(fileList: FileList)
{
   if(fileList.length > 0)
  {
    var reader = new FileReader();

      reader.onloadend = (e: Event) => {

      console.log(reader.result);
    }

    reader.readAsDataURL(fileList[0]);
  }
}

I can understand if this doesn't work altogether, but there are some rare instances where the onload/onloadend callback gets called and successfully converts the object to Base64 in my Android phone.

  • None of the callbacks are called including onerror unless the rarest of rarest occasions like I mentioned before.
  • The same code in the web browser works perfectly fine and the callbacks successfully gets called and converts the file object to Base64.

So this leaves me with very little options and I am unable to find a decent Base64 conversion plugin tailor made for angular 2 as most of the plugins around are for only the old angular.

One such plugin for angular had much promise - angular-base64-upload but I am unable to figure it out on how to run it in angular 2 as the instructions are specifically for the old angular.

Surely there must be a way to achieve this requirement, any leads would be highly appreciated.

My requirement is also such that the Base64 conversion plugin shouldn't be dependant upon any file path and should directly convert the file object got from file input selected by the user.

P.S: I already saw all the answers in stackoverflow with respect to the FileReader callbacks and none has worked for me so far.

2 Answers 2

3

Check this . https://plnkr.co/edit/PFfebmnqH0eQR9I92v0G?p=preview

Template

<input type="file" id="filePicker" (change)="handleFileSelect($event)">

Component:

handleFileSelect(evt){
      var files = evt.target.files;
      var file = files[0];

    if (files && file) {
        var reader = new FileReader();

        reader.onload =this._handleReaderLoaded.bind(this);

        reader.readAsBinaryString(file);
    }
  }

  _handleReaderLoaded(readerEvt) {
     var binaryString = readerEvt.target.result;
            this.base64textString= btoa(binaryString);
            console.log(btoa(binaryString));
    }

Edit : Regarding this not working in Mobile, it seems to be known issues in ionic. https://github.com/driftyco/ionic-native/issues/505

Things you can try

Loading zone.js before cordova.js also fixes it.

Specific to ionic2 maintain this sequence order.

<script src="build/polyfills.js"></script>
 <script src="cordova.js"</script>

as the polyfills.js executes the zone.js.

Sign up to request clarification or add additional context in comments.

5 Comments

I remember seeing this solution in another question and this was the first one which I tried initially but unfortunately it didn't work. Tried it again with the same plunker code to see if I missed anything, the issue still remains.
sorry, but what's the issue? u are getting base 64 of the file which u select
The issue is i am not able to get the base64 conversion when I run FileReader callbacks in an android phone (Nexus 6p running Nougat to be specific). The same works in a browser but not in a phone, though occasionally it works in my Nexus 6P with a success ratio of 1:100.
@PathGhiya - Thanks the exact answer would be load the <script src="build/polyfills.js"></script> before <script src="cordova.js"></script> @ index.html as the polyfills.js executes the zone.js. Please update your answer, as I expect more people to have this problem. Once you do this, i will accept this as the right answer :-). Thank you again for looking into this, you saved my day.
@VikramEzhil : you are welcomed :) yes many people will stumble upon this. you can accept & +1 :)
1

when i tried the previous solution the base 64 wasn't complete The html part

<input type="file" class="form-control input-lg" #fileInput type="file" accept="image/*" (change)="conImage($event)" name="Image"/>

the component side

conImage(input) :void{
    //this.profileService.conImage().subscribe(convertimage => this.convertimage = convertimage);
if (input.target.files && input.target.files[0]) {
    var reader = new FileReader();
    //data = data.replace(/['"]+/g, '');
    //$('#imageupload').attr('src', e.target.result);
    reader.onload = function (e) {
        console.log(e.target.result)
        //console.log(e)
    };
    reader.readAsDataURL(input.target.files[0]);
}

}

the console.log output gives a full base64 code, when you put the base64 in the src of an image you'll get the image

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.