E11上的JavaScript readAsBinaryString函数

时间:2015-07-13 18:52:24

标签: javascript html5 internet-explorer

在此页面http://www.html5rocks.com/en/tutorials/file/dndfiles/中,如果向下滚动到示例"示例:切片文件。试试吧!"您将看到使用 readAsBinaryString API来读取本地文件的字节。

我已经看到IE(我的情况是IE11)不支持 readAsBinaryString

即使在帖子HTML5 File API read as text and binary中提到的此代码也会在IE11中的 readAsBinaryString 处中断。

我在堆栈溢出中看到了一些帖子,它建议使用ReadAsArrayBuffer()。但它也没有用。它返回undefined。

我的问题是如果我必须在IE11上运行它有什么选择?是否可以编写另一个IE兼容的JS函数,它将执行readAsBinaryString()的JOB。

6 个答案:

答案 0 :(得分:41)

我将@Jack答案与我的评论结合起来,以展示一个完整的工作示例。

<head>部分,我添加了此脚本以在IE11中添加FileReader.readAsBinaryString功能

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);
    }
}

然后我需要稍微修改我原来的脚本代码,因为target.result在使用此回退功能时没有任何价值。

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);

答案 1 :(得分:30)

这是我的解决方案。

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);
    }
}

答案 2 :(得分:7)

对于IE 11,您可以使用此XHR技巧:

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();
}

它比Uint8Array + fromCharCode路线快20倍,速度只有readAsBinaryString

答案 3 :(得分:7)

heroku是一个非标准函数,已被弃用。

应该使用

FileReader.readAsBinaryString

MDN

答案 4 :(得分:2)

替换

reader.readAsBinaryString(blob);

使用:

reader.readAsText(blob);

它在跨浏览器中运行良好。

答案 5 :(得分:0)

我在这里的答案有一些问题,最后做了一些小改动。

我的解决方案不是将其分配给pt.content,而是将自定义对象发送到原型的加载对象,接收者可以专门查找该对象,我将此属性命名为msieContent,因此它非常具体。

我还使用了其他公认的答案,以更健壮的方式将Uint8Array转换为字符串,您可以在此处查看其详细信息: https://stackoverflow.com/a/12713326/213050

填充

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);
    }
}

用法

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);
}