如何使用JavaScript和XMLHttpRequest加载二进制图像数据?
我试图加载一个图像客户端和base64编码服务器返回的字节,以传递它来执行一些处理。 IE有一个XMLHttpRequest对象的RequestBody属性,但我似乎无法使用它,并且RequestText被截断。 在Firefox中,RequestText在那里,但似乎损坏。
这是我做的。
这个技巧是在另一个SO问题的答案中提供的,但这里也是相关的。
我不想base64编码任何东西。 我想通过Javascript在浏览器中下载和parsing二进制文件,而不用修改服务器来专门编码它们。 我发现,在Firefox中,通过强制通过overrideMimeType()
响应的MIMEtypes,我可以使用XMLHttpRequest.responseText
。 在IE上,这是不同的,因为:
-
IE上的
responseText
在第一个零处截断。 对于二进制stream,这是一个大问题。 -
没有
XMLHttpRequest.overrideMimeType()
,强制IE将二进制stream视为文本。 -
而
XMLHttpRequest.responseBody
(仅限IE!)是专门为二进制数据stream而devise的,令人难以置信的是该属性在Javascript中不可用。
因此,需要将IE的responseBody
属性转换成类似于来自FireFox的responseText
,使用mimetypes的强制。 这是可能的使用注入的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个位置的字节。
祝你好运。
感谢Miskun的VBScript转换逻辑。
如果你正在使用COTS,那么你总是可以build立一个中间网关,在这个网关中,请求被创build和转换(在这种情况下是base64编码),然后再返回给客户端。
您可以让服务器返回base64文本,而不是执行该编码客户端。
例如(在ASP.NET中),可以将对/ImageAsBase64.ashx?file=http://img.dovov.commyimage.png的请求编码为读取文件,base64对其进行编码,并将其作为响应进行stream式传输。
这真的会在PHP或任何其他相同的东西。