如何使用 Javascript 和 XMLHttpRequest 加载二进制图像数据? [英] How do I load binary image data using Javascript and XMLHttpRequest?

查看:23
本文介绍了如何使用 Javascript 和 XMLHttpRequest 加载二进制图像数据?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图加载图像客户端,并对服务器返回的字节进行 base64 编码,以便将其传递以执行一些处理.IE 有 XMLHttpRequest 对象的 RequestBody 属性,但我似乎无法使用它,并且 RequestText 被截断.在 Firefox 中,RequestText 存在,但似乎已损坏.

I was trying to load an image client side and base64 encode the bytes returned by the server in order to pass it off to perform some processing. IE has a RequestBody property of the XMLHttpRequest object, but I can't seem to use it, and RequestText is truncated. In Firefox, RequestText is there, but seems corrupted.

推荐答案

这是我的做法.

此技术在另一个 SO 问题的答案中提供,但它也与此处相关.

This technique is provided in an answer to another SO question, but it's also relevant here.

我不想对任何东西进行 base64 编码.我想通过 Javascript 在浏览器中下载和解析二进制文件,而不需要修改服务器来对它们进行特殊编码.我发现在 Firefox 中,通过通过 overrideMimeType() 强制响应的 mimetype,我可以使用 XMLHttpRequest.responseText.在 IE 上,它是不同的,因为:

I didn't want to base64 encode anything. I wanted to download and parse binary files in the browser via Javascript, without modifying the server to encode them specially. I found that in Firefox, by coercing the mimetype of the response via overrideMimeType(), I could use XMLHttpRequest.responseText. On IE, it's different because:

    IE 上的
  • responseText 在第一个零处截断.对于二进制流来说,这是一个大问题.

  • responseText on IE truncates at the first zero. For binary streams this is a big problem.

没有 XMLHttpRequest.overrideMimeType() 来强制 IE 将二进制流视为文本.

there is no XMLHttpRequest.overrideMimeType(), to force IE to treat binary streams as text.

虽然有一个 XMLHttpRequest.responseBody(仅限 IE!)专门设计用于二进制数据流,但令人抓狂的是该属性无法从 Javascript 中使用.

while there is a XMLHttpRequest.responseBody (IE only!) that is specifically designed to be used with binary data streams, maddeningly that property is not usable from Javascript.

因此,需要将 IE 的 responseBody 属性转换为类似于 FireFox 中的 responseText 的东西,带有 mime 类型的强制转换.这可以使用注入的 VBScript 实现.

Therefore, the need is to convert IE's responseBody property into a thing that looks like responseText from FireFox, with the mime-type coercion. This is possible using injected VBScript.

要使其跨浏览器,您只需在条件中打包特定于浏览器的逻辑.这是我用的:

To make it cross-browser, you need to just pack up the browser-specific logic in a conditional. This is what I used:

// one-time code
if(/msie/i.test(navigator.userAgent) && !/opera/i.test(navigator.userAgent)) {
    var IEBinaryToArray_ByteStr_Script =
    "<!-- IEBinaryToArray_ByteStr -->
"+
    "<script type='text/vbscript'>
"+
    "Function IEBinaryToArray_ByteStr(Binary)
"+
    "   IEBinaryToArray_ByteStr = CStr(Binary)
"+
    "End Function
"+
    "Function IEBinaryToArray_ByteStr_Last(Binary)
"+
    "   Dim lastIndex
"+
    "   lastIndex = LenB(Binary)
"+
    "   if lastIndex mod 2 Then
"+
    "       IEBinaryToArray_ByteStr_Last = Chr( AscB( MidB( Binary, lastIndex, 1 ) ) )
"+
    "   Else
"+
    "       IEBinaryToArray_ByteStr_Last = "+'""'+"
"+
    "   End If
"+
    "End Function
"+
    "</script>
";

    // inject VBScript
    document.write(IEBinaryToArray_ByteStr_Script);
}


// each time you make a request for a binary resource:
var req = (function() {
    if (window.XMLHttpRequest) {
        return new window.XMLHttpRequest();
    }
    else {
        try {
            return new ActiveXObject("MSXML2.XMLHTTP");
        }
        catch(ex) {
            return null;
        }
    }
})();

var fileContents = "";
var filesize = -1;
var readByteAt = function(i){
    return fileContents.charCodeAt(i) & 0xff;
};

req.open("GET", url, true);

if(/msie/i.test(navigator.userAgent) && !/opera/i.test(navigator.userAgent)) {
    // IE-specific logic here
    // helper to convert from responseBody to a "responseText" like thing
    var convertResponseBodyToText = function (binary) {
        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);
            }
        }
        var rawBytes = IEBinaryToArray_ByteStr(binary);
        var lastChr = IEBinaryToArray_ByteStr_Last(binary);
        return rawBytes.replace(/[sS]/g,
                                function( match ) { return byteMapping[match]; }) + lastChr;
    };

    req.setRequestHeader("Accept-Charset", "x-user-defined");
    req.onreadystatechange = function(event){
        if (req.readyState == 4) {
            if (req.status == 200) {
                fileContents = convertResponseBodyToText(req.responseBody);
                fileSize = fileContents.length-1;
                // invoke a callback here, if you like...
            }
            else{
                alert("download failed, status " + req.status);
            }
        }
    };
    req.send();

} else {
    // ff/Gecko/Webkit specific stuff here
    req.onreadystatechange = function(aEvt) {
        if (req.readyState == 4) { // completed
            if(req.status == 200){ // status == OK
                fileContents = binStream.req.responseText;
                filesize = fileContents.length;
                // invoke a callback here, if you like...
            }
            else {
                alert("download failed, status " + req.status);
            }
        }
    };
    // coerce response type
    req.overrideMimeType('text/plain; charset=x-user-defined');
    req.send(null);
}

...然后调用 readByte(i) 来获取二进制文件中 ith<​​/em> 位置的字节.

...then call readByte(i) to get the byte at the ith position in the binary file.

祝你好运.

归功于 Miskun 的 VBScript 转换逻辑.

Credit to Miskun for the VBScript conversion logic.

这篇关于如何使用 Javascript 和 XMLHttpRequest 加载二进制图像数据?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆