如何使用Javascript和XMLHttpRequest加载二进制图像数据?
我试图加载一个图像客户端和base64编码服务器返回的字节,以传递它来执行一些处理。 IE有一个XMLHttpRequest对象的RequestBody属性,但我似乎无法使用它,并且RequestText被截断。在Firefox中,RequestText在那里,但似乎损坏。如何使用Javascript和XMLHttpRequest加载二进制图像数据?
您可以让服务器返回base64文本,而不是执行该编码客户端。
例如,(在ASP.NET中)可以将对/ImageAsBase64.ashx?file=/images/myimage.png的请求编码为读取文件,base64对其进行编码并将其作为响应进行流式传输。
它真的是非常的PHP或任何同样的事情。
不幸的是,在这种情况下无法工作 - 我需要某些COTS软件的数据,而且它没有base64选项。 – 2009-07-07 22:06:18
如果您使用COTS,你总是可以建立一个中间网关,其中提出要求和转化的(Base64在这种情况下,编码)到的东西被返回给客户端之前更可口。
我其实已经试过了;但是,图像是特定于用户会话的,我无法将软件伪装成认为服务器是同一用户会话的一部分。 – 2009-07-08 13:42:07
下面是我做到的。在回答中提供给其它SO问题
这种技术,但它也与此有关。
我不想base64编码任何东西。我想通过Javascript下载并解析浏览器中的二进制文件,而不需要修改服务器来专门对其进行编码。我发现在Firefox中,通过强制通过overrideMimeType()
响应的MIME类型,我可以使用XMLHttpRequest.responseText
。在IE上,它的不同之处在于:
responseText
IE在第一个零处截断。对于二进制流,这是一个很大的问题。没有
XMLHttpRequest.overrideMimeType()
,强制IE将二进制流视为文本。虽然有一个专门设计用于二进制数据流的
XMLHttpRequest.responseBody
(仅限IE!),令人疯狂的是,该属性在Javascript中不可用。
因此,需要的是IE的responseBody
财产转换成看起来像responseText
从Firefox,用MIME类型强制的事情。这可以使用注入的VBScript。
为了让跨浏览器,你只是需要收拾在有条件的浏览器特定的逻辑。这是我用什么:
// one-time code
if(/msie/i.test(navigator.userAgent) && !/opera/i.test(navigator.userAgent)) {
var IEBinaryToArray_ByteStr_Script =
"<!-- IEBinaryToArray_ByteStr -->\r\n"+
"<script type='text/vbscript'>\r\n"+
"Function IEBinaryToArray_ByteStr(Binary)\r\n"+
" IEBinaryToArray_ByteStr = CStr(Binary)\r\n"+
"End Function\r\n"+
"Function IEBinaryToArray_ByteStr_Last(Binary)\r\n"+
" Dim lastIndex\r\n"+
" lastIndex = LenB(Binary)\r\n"+
" if lastIndex mod 2 Then\r\n"+
" IEBinaryToArray_ByteStr_Last = Chr(AscB(MidB(Binary, lastIndex, 1)))\r\n"+
" Else\r\n"+
" IEBinaryToArray_ByteStr_Last = "+'""'+"\r\n"+
" End If\r\n"+
"End Function\r\n"+
"</script>\r\n";
// 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(/[\s\S]/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个位置拿到字节。
祝你好运。
Credit to Miskun为VBScript转换逻辑。
经过几天的努力,我能够完成这项工作,尽管互联网上进行这种二元操作的信息相当稀少。我认为这可能对其他人有用,特别是在处理数据URI时,所以我详细介绍了我的工作:[http://emilsblog.lerch.org/2009/07/javascript-hacks-using-xhr-to- load.html](HTTP://emilsblog.lerch。org/2009/07/javascript-hacks-using-xhr-to-load.html) – 2009-07-07 22:01:36