29

In this page http://www.html5rocks.com/en/tutorials/file/dndfiles/ if you scroll down to example "Example: Slicing a file. Try it!" you will see uses of readAsBinaryString API to read bytes of local files.

I've seen IE (My case its IE11) doesn't support readAsBinaryString.

Even this code mentioned in post HTML5 File API read as text and binary breaks at readAsBinaryString in IE11.

I have seen some post in stack overflow, it suggests use of ReadAsArrayBuffer(). But it is also not working. It returns undefined.

My question is what are the options if I have to run it on IE11? Is it possible to write another IE compatible JS function which will do the JOB of readAsBinaryString().

6 Answers 6

52

I combine @Jack answer with my comment to show a complete working example.

In the <head> section I added this script to add FileReader.readAsBinaryString function in IE11

if (FileReader.prototype.readAsBinaryString === undefined) {
    FileReader.prototype.readAsBinaryString = function (fileData) {
        var binary = "";
        var pt = this;
        var reader = new FileReader();
        reader.onload = function (e) {
            var bytes = new Uint8Array(reader.result);
            var length = bytes.byteLength;
            for (var i = 0; i < length; i++) {
                binary += String.fromCharCode(bytes[i]);
            }
            //pt.result  - readonly so assign content to another property
            pt.content = binary;
            pt.onload(); // thanks to @Denis comment
        }
        reader.readAsArrayBuffer(fileData);
    }
}

Then I needed to slightly modify my original script code because target.result has no value when using this fallback function.

var reader = new FileReader();
reader.onload = function (e) {
    // ADDED CODE
    if (!e) {
        var data = reader.content;
    }
    else {
        var data = e.target.result;
    }

    // business code
};
reader.readAsBinaryString(myFile);
Sign up to request clarification or add additional context in comments.

5 Comments

$(pt).trigger('onload'); is it jQuery's trigger method? How to do dispatch this event without jQuery?
Jack + Naigel = Just saved my day
@Denis added your suggestion, it was the only code line requiring jQuery and was easy to change with vanilla JS.
@NachPD glad to help someone else, I've already wasted hours on that point, let's make them worthy ;)
Why not always use e.target.result? Is !e ever true?
36

This is my solution.

var reader = new FileReader();
reader.readAsBinaryString(fileData);
reader.onload = function(e) {
  if (reader.result) reader.content = reader.result;
  var base64Data = btoa(reader.content);
  //...
}
//extend FileReader
if (!FileReader.prototype.readAsBinaryString) {
    FileReader.prototype.readAsBinaryString = function (fileData) {
       var binary = "";
       var pt = this;
       var reader = new FileReader();      
       reader.onload = function (e) {
           var bytes = new Uint8Array(reader.result);
           var length = bytes.byteLength;
           for (var i = 0; i < length; i++) {
               binary += String.fromCharCode(bytes[i]);
           }
        //pt.result  - readonly so assign binary
        pt.content = binary;
        $(pt).trigger('onload');
    }
    reader.readAsArrayBuffer(fileData);
    }
}

3 Comments

in the main code I was using FileReader this way: var reader = new FileReader(); reader.onload = function (e) { var data = e.target.result; ..CODE HERE.. }; reader.readAsBinaryString(myFile). I needed to change reader.onload this way: reader.onload = function (e) { if (!e) {var data = reader.content;} else {var data = e.target.result; } ..CODE HERE.. };
@Naigel comment was very helpful with the change he wrote. combining Jacks code and Naigels worked for me
$(pt).trigger('onload'); is it jQuery's trigger method? How to do dispatch this event without jQuery?
9

FileReader.readAsBinaryString is a non-standard function and has been deprecated.

FileReader.readAsArrayBuffer should be used instead.

MDN

Comments

7

For IE 11 you can use this XHR trick:

function blobToBinaryStringIE11(blob) {
    var blobURL = URL.createObjectURL(blob);
    var xhr = new XMLHttpRequest;
    xhr.open("get", blobURL);
    xhr.overrideMimeType("text/plain; charset=x-user-defined");
    xhr.onload = function () {
        var binary = xhr.response;
        // do stuff
    };
    xhr.send();
}

It's 20x faster than the Uint8Array + fromCharCode route and as fast as readAsBinaryString.

Comments

1

Replace

reader.readAsBinaryString(blob);

with:

reader.readAsText(blob);

it's works well in cross browser.

1 Comment

There are problems with this. Since the browser thinks its text and not binary it can cause errors for example in firefox I got invalid characters error.
0

I had some problems with the answers here and ended up making a few slight changes.

Instead of assigning to pt.content, my solution is to send a custom object to the prototype's onload, that receiver can specifically look for, I named this property msieContent so it will be very specific.

Also I used other accepted answer for converting Uint8Array to string in more robust way, you can see full details of it here: https://stackoverflow.com/a/12713326/213050

Polyfill

if (FileReader.prototype.readAsBinaryString === undefined) {
    // https://stackoverflow.com/a/12713326/213050
    function Uint8ToString(u8a: Uint8Array) {
        const CHUNK_SZ = 0x8000;
        let c = [];
        for (let i = 0; i < u8a.length; i += CHUNK_SZ) {
            c.push(String.fromCharCode.apply(null, u8a.subarray(i, i + CHUNK_SZ)));
        }
        return c.join('');
    }
    FileReader.prototype.readAsBinaryString = function (fileData) {
        const reader = new FileReader();
        reader.onload = () => this.onload({
            msieContent: Uint8ToString(new Uint8Array(<any>reader.result))
        });
        reader.readAsArrayBuffer(fileData);
    }
}

Usage

private _handleTextFile(file: File) {
    const reader = new FileReader();

    reader.onload = (e) => {
        // support for msie, see polyfills.ts
        const readResult: string = (<any>e).msieContent || <string>e.target.result;

    };

    reader.readAsBinaryString(file);
}

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.