Skip to content

Instantly share code, notes, and snippets.

@abbotto
Last active April 26, 2024 08:13
Show Gist options
  • Save abbotto/5a78b0094a395b860759 to your computer and use it in GitHub Desktop.
Save abbotto/5a78b0094a395b860759 to your computer and use it in GitHub Desktop.
Get binary data with XHR in most browsers including IE8+
/*!
* xhrBinary.js
* Author: Jared Abbott
* Copyright 2015 Jared Abbott
* Distributed under the MIT license
*/
var xhrBinary = function(url, fn) {
// RESOURCES
// http://mgran.blogspot.com/2006/08/downloading-binary-streams-with.html
// http://miskun.com/javascript/internet-explorer-and-binary-files-data-access/
// http://stackoverflow.com/questions/9267899/arraybuffer-to-base64-encoded-string
// https://msdn.microsoft.com/en-us/library/y39d47w8(v=VS.85).aspx
// https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/Sending_and_Receiving_Binary_Data
// USAGE
// xhrBinary(url, function(data){
// // Encode the string w/ Base64
// var base64 = 'data:application/octet-stream;base64,'+btoa(data);
// });
var request = window.XMLHttpRequest || ActiveXObject;
var xhr = new request("MSXML2.XMLHTTP.3.0");
var data = '';
var buffer = '';
var bufferLength = 0;
// Retrieve the file
xhr.open('GET', url, true);
// XMLHttpRequest2-compliant browsers
if (!!window.Uint8Array) {
xhr.responseType = "arraybuffer";
}
// XMLHttpRequest-compliant browsers
else if ('overrideMimeType' in xhr) {
xhr.overrideMimeType('text\/plain; charset=x-user-defined');
}
// Microsoft.XMLHTTP-compliant browsers [IE9]
else {
xhr.setRequestHeader('Accept-Charset', 'x-user-defined');
}
xhr.onreadystatechange = function(e) {
if (this.readyState == 4 && this.status == 200) {
// Handles most browsers with a fallback for IE9
if (!!window.Uint8Array || !!window.VBArray) {
// In IE9 and below the responseBody property returns a byte array in VBArray format
// VBArray is not directly usable 'as is' with JavaScript.
// In IE9+ we can access the bytes by converting the VBArray to a JS-compatible array
// with the VBArray.toArray() method.
buffer = (!!window.Uint8Array) ? new Uint8Array(xhr.response) : xhr.responseBody.toArray();
data = String.fromCharCode.apply(null, buffer);
}
// IE8
else if (!!window.execScript) {
buffer = xhr.responseBody;
var parseVBArray = function (buffer) {
// VBScript
var VBScript =
"Function binToArrByteStr(buffer)\r\n"+
" binToArrByteStr = CStr(buffer)\r\n"+
"End Function\r\n"+
"Function binToArrByteStr_Last(buffer)\r\n"+
" Dim lastIndex\r\n"+
" lastIndex = LenB(buffer)\r\n"+
" if lastIndex mod 2 Then\r\n"+
" binToArrByteStr_Last = AscB( MidB( buffer, lastIndex, 1 ) )\r\n"+
" Else\r\n"+
" binToArrByteStr_Last = -1\r\n"+
" End If\r\n"+
"End Function\r\n";
// Execute VBScript
window.execScript(VBScript);
// Mapper
var byteMapping = {};
for ( var i = 0; i < 256; i++ ) {
for ( var j = 0; j < 256; j++ ) {
byteMapping[String.fromCharCode(i + j * 256)] = String.fromCharCode(i) + String.fromCharCode(j);
}
}
// Data
var rawBytes = binToArrByteStr(buffer);
var lastChr = binToArrByteStr_Last(buffer);
return rawBytes.replace(/[\s\S]/g, function( match ) { return byteMapping[match]; }) + lastChr;
}
data = parseVBArray(buffer);
}
// Other browsers
else {
buffer = xhr.responseText;
bufferLength = buffer.length;
for (var i = 0, len = bufferLength; i < len; ++i) {
// Throw away high-order bytes at offset i (f7)
data += String.fromCharCode(buffer.charCodeAt(i) & 255) // 255 === 0xff
}
}
// Return the binary
if (typeof fn !== 'undefined') {
fn(data);
} else {
return data;
}
}
};
xhr.send(null);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment