如何使用Javascript和XMLHttpRequest加载二进制图像数据?

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


这是我做到的。

这种技术是在另一个SO问题的答案中提供的,但这里也是相关的。

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

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

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

  • 尽管XMLHttpRequest.responseBody (IE only!)专门用于与二进制数据流一起使用,但令人愤慨的是,该属性在Javascript中不可用。

  • 因此,需要将IE的responseBody属性转换为类似于来自FireFox的responseText ,并进行mime类型的强制转换。 这可以使用注入的VBScript。

    为了使它跨浏览器,你需要在条件语言中打包浏览器特定的逻辑。 这是我用过的:

    // one-time code
    if(/msie/i.test(navigator.userAgent) && !/opera/i.test(navigator.userAgent)) {
        var IEBinaryToArray_ByteStr_Script =
        "<!-- IEBinaryToArray_ByteStr -->rn"+
        "<script type='text/vbscript'>rn"+
        "Function IEBinaryToArray_ByteStr(Binary)rn"+
        "   IEBinaryToArray_ByteStr = CStr(Binary)rn"+
        "End Functionrn"+
        "Function IEBinaryToArray_ByteStr_Last(Binary)rn"+
        "   Dim lastIndexrn"+
        "   lastIndex = LenB(Binary)rn"+
        "   if lastIndex mod 2 Thenrn"+
        "       IEBinaryToArray_ByteStr_Last = Chr( AscB( MidB( Binary, lastIndex, 1 ) ) )rn"+
        "   Elsern"+
        "       IEBinaryToArray_ByteStr_Last = "+'""'+"rn"+
        "   End Ifrn"+
        "End Functionrn"+
        "</script>rn";
    
        // 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)来获取二进制文件中第i个位置的字节。

    祝你好运。

    感谢Miskun的VBScript转换逻辑。


    如果你使用的是COTS,你总是可以建立一个中间网关,在这个网关中,请求被创建和转换(在这种情况下是base64编码),然后返回给客户端,再转变为更美味的东西。


    您可以让服务器返回base64文本,而不是执行该编码客户端。

    例如,(在ASP.NET中)可以对/ImageAsBase64.ashx?file=/images/myimage.png的请求进行编码以读取文件,对base64进行编码并作为响应进行流式传输。

    这真的会在PHP或其他方面几乎相同的东西。

    链接地址: http://www.djcxy.com/p/71743.html

    上一篇: How do I load binary image data using Javascript and XMLHttpRequest?

    下一篇: handle jquery ajax redirect