从XHR请求获取BLOB数据

Nic*_*net 35 javascript webkit blob xmlhttprequest

var xhr = new XMLHttpRequest();
xhr.open('GET', 'http://static.reddit.com/reddit.com.header.png', true);

xhr.responseType = 'arraybuffer';

xhr.onload = function(e) {
  if (this.status == 200) {
    var uInt8Array = new Uint8Array(this.response);
    var byte3 = uInt8Array[4]; 

    var bb = new WebKitBlobBuilder();
    bb.append(xhr.response);
    var blob = bb.getBlob('image/png'); 
    var base64 = window.btoa(blob);
    alert(base64);

  }
};

xhr.send();
Run Code Online (Sandbox Code Playgroud)

基本上,我在这里尝试做的是检索图像,并将其转换为base64.

通过阅读这里的评论,它说"当然.在将资源作为ArrayBuffer获取后,从中创建一个blob.一旦你有了,你可以直接对文件/ blob进行base64编码(window.btoa())或FileReader. readAsDataURL()".

然而,window.btoa()只是[对象blob],而我需要从图像中获取二进制文件,以便我可以将其转换为base64并使用数据将其显示在img标记中:

谁知道如何实现这一目标?

先感谢您!

Sco*_*t A 58

不要在Chrome中使用BlobBuilder(在OSX Chrome,Firefox 12,Safari 6,iOS Chrome,iOS Safari中测试):

ex1:http://jsfiddle.net/malraux/xGUsu/(原则)

ex2:http://jsfiddle.net/xGUsu/78/(使用完整示例)

var xhr = new XMLHttpRequest();
xhr.open('GET', 'doodle.png', true);

xhr.responseType = 'arraybuffer';

// Process the response when the request is ready.
xhr.onload = function(e) {
  if (this.status == 200) {
    // Create a binary string from the returned data, then encode it as a data URL.
    var uInt8Array = new Uint8Array(this.response);
    var i = uInt8Array.length;
    var binaryString = new Array(i);
    while (i--)
    {
      binaryString[i] = String.fromCharCode(uInt8Array[i]);
    }
    var data = binaryString.join('');

    var base64 = window.btoa(data);

    document.getElementById("myImage").src="data:image/png;base64," + base64;
  }
};

xhr.send();
Run Code Online (Sandbox Code Playgroud)

  • 谢谢!正是我在寻找的!斯科特A,你是我眼中的神.确认它有效:) (2认同)
  • 这对我来说非常好。谢谢@ScottA (2认同)

Jan*_*sen 40

你可以获取Blob并使用window.URL.createObjectURL.这可以防止构建巨型字符串并复制所有内容几次.

var xhr = new XMLHttpRequest();
xhr.open('GET', 'https://i.imgur.com/sBJOoTm.png', true);

xhr.responseType = 'blob';

xhr.onload = function(e) {
  if (this.status == 200) {
var blob = this.response;
document.getElementById("myImage").src = window.URL.createObjectURL(blob);
  }
};

xhr.onerror = function(e) {
  alert("Error " + e.target.status + " occurred while receiving the document.");
};

xhr.send();
Run Code Online (Sandbox Code Playgroud)
<img id="myImage">
Run Code Online (Sandbox Code Playgroud)

示例(相同代码):http://jsfiddle.net/ysangkok/sJxXk/86/.适用于Firefox和Chrome 25+.除了Opera Mini之外的所有其他浏览器:http://caniuse.com/#search=Blob

  • Blob构造函数仅在最新的浏览器中可用.例如,如果您必须支持IE8或9,则无法使用它. (2认同)
  • @JanusTroelsen如果你必须支持其中一个浏览器,这绝对没有任何意义(并且它比Firefox使用的百分比更高).:-)顺便说一下,IE10只有<4%,所以你基本上认为开发人员应该完全忽略IE,如果你看NetApplications而不是StatCounter,那么IE 8 + 9就是桌面的44%.话虽如此,你的Blob解决方案无效:OS X上的Safari 6.0.2,OS X上的Firefox 12,iPhone 4s上的Safari和Chrome. (2认同)
  • @JanusTroelsen现在你正在进行政治争论,而不是实际的争论.非自由与免费不是我们这些必须在现实世界中谋生的人的选择,但如果你能够支持自己并坚持不饶恕的立场,那么对你有更大的权力.我个人有一个非常大的企业客户端,最近在18个月前仍然在内部使用IE6,现在是在IE8上.我没有选择告诉他们我只支持Chrome或Firefox,因为它们是免费软件. (2认同)

Yas*_*ash 8

XMLHttpRequest的

var xmlhttp = new XMLHttpRequest();
xmlhttp.open('GET', 'http://RestServiceURL-Returns Image', true);
xmlhttp.setRequestHeader('Content-type','application/x-www-form-urlencoded');
xmlhttp.responseType = 'arraybuffer/blob';
xmlhttp.send();
Run Code Online (Sandbox Code Playgroud)

以3种方式创建blob图像.

  • window.URL.createObjectURL
  • FileReader(caniuse)
  • Base64String

    xmlhttp.onload = function() {
        var blob = new Blob([this.response], {type: 'image/png'}); 
        console.log(blob, blob.type, this.response, typeof this.response);  
    
        var image = document.getElementById('my-image');
    
        1)image.src = window.URL.createObjectURL(blob);
    
        2)var fileReader = new window.FileReader();
        fileReader.readAsDataURL(blob);
        fileReader.onloadend = function() { 
        image.src = fileReader.result;
        }
    
        3)var base64String = btoa(String.fromCharCode.apply(null, new Uint8Array(this.response)));
        image.src = 'data:image/png;base64,'+base64String;
    };
    
    Run Code Online (Sandbox Code Playgroud)

将ArrayBuffer转换为Blob转换为ArrayBuffer

1)var dataView = new DataView(arrayBuffer);
var blob = new Blob([dataView], { type: mimeString });


2)fileReader.readAsArrayBuffer(blob);
var arrayBuffer;
fileReader.onload = function() {
    arrayBuffer = this.result;
};
Run Code Online (Sandbox Code Playgroud)


Jak*_*b E 6

Janus Troelsen建议的解决方案相同,并添加了承诺......

笔记! 使用createObjectURL 时- 不要忘记调用revokeObjectURL

//  Load blob (promise)
function loadBlob( url ){
    return new Promise( (resolve, reject) => {
        const xhr = new XMLHttpRequest();
        xhr.open('GET', url, true);
        xhr.responseType = 'blob';        
        xhr.onload  = () => resolve(xhr.response);
        xhr.onerror = () => reject(xhr.statusText);        
        xhr.send();
    });
}

//  Create image from blob (createObjectURL)
function imageFromBlob( blob ){ 
    const img = new Image();
    img.onload = () => URL.revokeObjectURL(img.src);
    img.src = URL.createObjectURL(blob);    
    return img;
}


//  Create image from blob if loaded successfully
loadBlob('https://unsplash.it/960/540?random')
    .then( blob => {
        document.body.appendChild( imageFromBlob(blob) );      
    })
    .catch( error => {
        console.log('Could not load image');
    })
    


//  Alternate version adding promise to xhr
//  if you like to trigger xhr.send() yourself
function xhrBlob(url){
    const xhr = new XMLHttpRequest();
    xhr.open('GET', url, true);
    xhr.responseType = 'blob';        
    xhr.promise = new Promise((resolve, reject) => {
        xhr.onload  = () => resolve(xhr.response);
        xhr.onerror = () => reject(xhr.statusText);  
    });
    xhr.load = ( onsuccess = () => {}, onerror = () => {} ) => { 
        xhr.promise.then(onsuccess).catch(onerror);
        xhr.send();
        return xhr;
    }
    return xhr;
}


//  Using load callbacks
xhrBlob('https://unsplash.it/960/540?random')
    .load( 
        //  on sussess
        blob => {
            document.body.appendChild( imageFromBlob(blob) );      
        },
        //  on error
        error => {
            console.log('Could not load image');
        }
    );
    
 //  Using promise (delayed)
const image = xhrBlob('https://unsplash.it/960/540?random');

    //  Promise handlers
    image.promise
    .then( blob => {
        document.body.appendChild( imageFromBlob(blob) );      
    })
    .catch( error => {
        console.log('Could not load image');
    });
 
 //  Load image (will trigger promise handlers)
 setTimeout(image.load, 3000);
Run Code Online (Sandbox Code Playgroud)
img {
  width: 100%;
}
Run Code Online (Sandbox Code Playgroud)