how do I access XHR responseBody from Javascript?

Posted by Cheeso on Stack Overflow See other posts from Stack Overflow or by Cheeso
Published on 2009-12-17T07:09:52Z Indexed on 2010/06/16 2:32 UTC
Read the original article Hit count: 648

Filed under:
|

I've got a web page that uses XMLHttpRequest to download a binary resource.

Because it's binary I'm trying to use xhr.responseBody to access the bytes. I've seen a few posts suggesting that it's impossible to access the bytes directly from Javascript. This sounds crazy to me.

Weirdly, xhr.responseBody is accessible from VBScript, so the suggestion is that I must define a method in VBScript in the webpage, and then call that method from Javascript. See jsdap for one example.

var IE_HACK = (/msie/i.test(navigator.userAgent) && 
               !/opera/i.test(navigator.userAgent));   

if (IE_HACK) document.write('<script type="text/vbscript">\n\
     Function BinaryToArray(Binary)\n\
         Dim i\n\
         ReDim byteArray(LenB(Binary))\n\
         For i = 1 To LenB(Binary)\n\
             byteArray(i-1) = AscB(MidB(Binary, i, 1))\n\
         Next\n\
         BinaryToArray = byteArray\n\
     End Function\n\
</script>'); 

var xml = (window.XMLHttpRequest) 
    ? new XMLHttpRequest()      // Mozilla/Safari/IE7+
    : (window.ActiveXObject) 
      ? new ActiveXObject("MSXML2.XMLHTTP")  // IE6
      : null;  // Commodore 64?


xml.open("GET", url, true);
if (xml.overrideMimeType) {
    xml.overrideMimeType('text/plain; charset=x-user-defined');
} else {
    xml.setRequestHeader('Accept-Charset', 'x-user-defined');
}

xml.onreadystatechange = function() {
    if (xml.readyState == 4) {
        if (!binary) {
            callback(xml.responseText);
        } else if (IE_HACK) {
            // call a VBScript method to copy every single byte
            callback(BinaryToArray(xml.responseBody).toArray());
        } else {
            callback(getBuffer(xml.responseText));
        }
    }
};
xml.send('');

Is this really true? The best way? copying every byte? For a large binary stream that's not gonna be very efficient.

There is also a possible technique using ADODB.Stream, which is a COM equivalent of a MemoryStream. See here for an example. It does not require VBScript but does require a separate COM object.

if (typeof (ActiveXObject) != "undefined" && typeof (httpRequest.responseBody) != "undefined") {
    // Convert httpRequest.responseBody byte stream to shift_jis encoded string
    var stream = new ActiveXObject("ADODB.Stream");
    stream.Type = 1; // adTypeBinary
    stream.Open ();
    stream.Write (httpRequest.responseBody);
    stream.Position = 0;
    stream.Type = 1; // adTypeBinary;
    stream.Read....          /// ???? what here
}

I don't think that's gonna work - ADODB.Stream is disabled on most machines these days.


In The IE8 developer tools - the IE equivalent of Firebug - I can see the responseBody is an array of bytes and I can even see the bytes themselves. The data is right there. I don't understand why I can't get to it.

Is it possible for me to read it with responseText?

hints? (other than defining a VBScript method)

© Stack Overflow or respective owner

Related posts about JavaScript

Related posts about xmlhttprequest