【问题标题】:Get image base64 with reader.readAsArrayBuffer(file)使用 reader.readAsArrayBuffer(file) 获取图像 base64
【发布时间】:2018-05-25 18:06:52
【问题描述】:

我正在尝试获取 base64 字符串中的图像内容。

最初我是用readAsDataURLbecause I want to validate the mimetype on the client side 做的,看来我必须使用readAsArrayBuffer,正如on this site 所指出的那样。

所以以前我可以正常工作:

var reader = new FileReader();
reader.onloadend = function(event) {
    var base64 = reader.result;
};

reader.readAsDataURL(event.target.files[0]);

Reproduction online

现在我添加了 mimetype 验证,我有以下内容:

var reader = new FileReader();

reader.onloadend = function(event) {

    var realMimeType = getRealMimeType(reader);

    if (realMimeType !== 'unknown') {
        var emptyBufferArray = reader.result; //nothing
    }else{
        alert("Invalid mime type!");
    }
};

reader.readAsArrayBuffer(event.target.files[0]); //<-- notice the difference

Reproduction online(未获取 base64 字符串)

【问题讨论】:

    标签: javascript


    【解决方案1】:

    我发现这样做的唯一方法是使用两个不同的 FileReader 实例,一个在另一个内部。

    Reproduction online

    Javascript

    $(document).on('change', '#upload', addBackgroundImage);
    
    function addBackgroundImage(event) {
        var reader = new FileReader();
        var readerBase64 = new FileReader();
        var image = event.target.files[0];
    
        reader.onloadend = function() {
            var realMimeType = getRealMimeType(reader);
            if (realMimeType !== 'unknown') {
                readerBase64.readAsDataURL(image);
            } else {
                alert("Please upload a valid image file");
            }
        };
    
        reader.readAsArrayBuffer(image);
    
        readerBase64.onloadend = function(){
            var base64 = this.result;
            $('.bg').css('background-image', 'url('+base64+')');
        };
    
        $('#upload').val('');
    }
    
    function getRealMimeType(reader){
        var arr = (new Uint8Array(reader.result)).subarray(0, 4);
        var header = '';
        var realMimeType;
    
        for (var i = 0; i < arr.length; i++) {
            header += arr[i].toString(16);
        }
    
        // magic numbers: http://www.garykessler.net/library/file_sigs.html
        switch (header) {
            case "89504e47":
                realMimeType = "image/png";
                break;
            case "47494638":
                realMimeType = "image/gif";
                break;
            case "ffd8ffDB":
            case "ffd8ffe0":
            case "ffd8ffe1":
            case "ffd8ffe2":
            case "ffd8ffe3":
            case "ffd8ffe8":
                realMimeType = "image/jpeg";
                break;
            default:
                realMimeType = "unknown"; // Or you can use the blob.type as fallback
                break;
        }
    
        return realMimeType;
    }
    

    HTML

    <input type="file" id="upload" />
    <div class="bg"></div>
    

    【讨论】:

    【解决方案2】:

    我还没有设法使用base64,但我找到了使用blob 的方法。 如果您找到使用base64 的方法,请添加您的答案。

    现在我的图像字符串看起来像这样,我相信这会给我带来一些问题:

     background-image: url("blob:https%3A//fiddle.jshell.net/214b3c01-5b38-4aae-b839-e35cf57a5190");
    

    我从小提琴中得到了关于how to render a retrieved image as a blob URL的提示

    然后我用a little improvement 将它应用到我的代码中,瞧!!

    Reproduction online 工作在 IE> 9、Chrome、Firefox...

    完整代码:

    HTML

    <input type="file" id="upload" />
    <div class="bg"></div>
    

    Javascript

    $(document).on('change', '#upload', addBackgroundImage);
    
    function addBackgroundImage(event) {
        var reader = new FileReader();
    
        reader.onloadend = function(event) {
            var realMimeType = getRealMimeType(reader);
    
            if (realMimeType !== 'unknown') {
                var base64 = reader.result;
    
                var arrayBufferView = new Uint8Array( this.result );
                var blob = new Blob( [ arrayBufferView ], { type: realMimeType } );
                var urlCreator = window.URL || window.webkitURL || {}.createObjectURL;
                var imageUrl = urlCreator.createObjectURL( blob );
    
                $('.bg').css('background-image', 'url('+imageUrl+')');
            } else {
                alert("Please upload a valid image file");
            }
        }
        reader.readAsArrayBuffer(event.target.files[0]);
         $('#upload').val('');
    }
    
    function getRealMimeType(reader){
        var arr = (new Uint8Array(reader.result)).subarray(0, 4);
        var header = '';
        var realMimeType;
    
        for (var i = 0; i < arr.length; i++) {
            header += arr[i].toString(16);
        }
    
        // magic numbers: http://www.garykessler.net/library/file_sigs.html
        switch (header) {
            case "89504e47":
                realMimeType = "image/png";
                break;
            case "47494638":
                realMimeType = "image/gif";
                break;
            case "ffd8ffDB":
            case "ffd8ffe0":
            case "ffd8ffe1":
            case "ffd8ffe2":
            case "ffd8ffe3":
            case "ffd8ffe8":
                realMimeType = "image/jpeg";
                break;
            default:
                realMimeType = "unknown"; // Or you can use the blob.type as fallback
                break;
        }
    
        return realMimeType;
    }
    

    【讨论】:

      【解决方案3】:

      你可以试试这个"stolen"函数:

      function arrayBufferToBase64(buffer) {
        let binary = '';
        const bytes = new Uint8Array(buffer);
        const len = bytes.byteLength;
        for (let i = 0; i < len; i++) {
          binary += String.fromCharCode(bytes[i]);
        }
        return window.btoa(binary);
      }
      

      【讨论】:

      • 它有效,但是否存在性能问题? for 循环和 binary += 执行次数过多。
      • 我将+= 部分重写为以下代码:function arrayBufferToBase64(buffer) { var bytes = new Uint8Array(buffer); var chars = []; var len = bytes.byteLength; for (let i=0; i&lt;len; i++) { chars.push(String.fromCharCode(bytes[i])) } var binary = chars.join(''); return window.btoa(binary); }
      【解决方案4】:

      以下解决方案仅使用一个 FileReader 对我有用:

      reader.onloadend = function(event) {
          const arrayBuffer = reader.result;
          const blob = new Blob([arrayBuffer], {type: 'image/png'});
          let src = URL.createObjectURL(blob);
      };
      reader.readAsArrayBuffer(event.target.files[0]); 
      

      希望有帮助!

      【讨论】:

        猜你喜欢
        • 2018-02-06
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-01-24
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-12-05
        相关资源
        最近更新 更多