我有一个使用XMLHttpRequest来下载二进制资源的网页。
在Firefox和Gecko中,即使字节流包含二进制零,我也可以使用responseText来获取字节。我可能需要强迫模仿overrideMimeType()
才能实现。但是,在IE中,responseText不起作用,因为它似乎在第一个零处终止。如果读取100,000个字节,并且字节7为二进制零,则只能访问7个字节。IE的XMLHttpRequest公开了一个responseBody
属性来访问字节。我看到一些帖子暗示不可能直接从Javascript以任何有意义的方式访问此属性。这对我来说听起来很疯狂。
xhr.responseBody
_是_从VBScript访问,因此明显的解决方法是在VBScript在网页中定义的方法,然后从JavaScript调用该方法。
编辑:请勿使用此VBScript!
var IE_HACK = (/msie/i.test(navigator.userAgent) &&
!/opera/i.test(navigator.userAgent));
// no no no! Don't do this!
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('');
这是真的吗?最好的方式?复制每个字节?对于大型二进制流,效率将不高。
还有一种 可能的 技术是使用ADODB.Stream,它与MemoryStream等效于COM。它不需要VBScript,但是需要单独的COM对象。
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
}
但这不能很好地工作-如今,大多数计算机上都禁用了ADODB.Stream。
在IE8开发人员工具(相当于IE的Firebug)中,我可以看到responseBody是字节数组,甚至可以看到字节本身。数据 就在那里
。我不明白为什么我不能做到这一点。
我可以用responseText读取它吗?
提示?(除了定义VBScript方法之外)
是的,我想通过IE中的XHR读取二进制数据的答案是使用VBScript注入。一开始这对我来说很令人讨厌,但是,我将其视为仅仅是一个依赖于浏览器的代码。(常规XHR和responseText在其他浏览器中可以正常工作;您可能必须使用来强制MIME类型。IEXMLHttpRequest.overrideMimeType()
]上不提供此功能)。
这就是我得到的东西responseText
即使在二进制数据中也可以在IE中工作的方式。首先,一次性注入一些VBScript,如下所示:
if(/msie/i.test(navigator.userAgent) && !/opera/i.test(navigator.userAgent)) {
var IEBinaryToArray_ByteStr_Script =
"<!-- IEBinaryToArray_ByteStr -->\r\n"+
"<script type='text/vbscript' language='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);
}
我正在使用的读取二进制文件的JS类公开了一个有趣的方法readCharAt(i)
,该方法读取第i个索引处的字符(实际上是一个字节)。这是我的设置方式:
// see doc on http://msdn.microsoft.com/en-us/library/ms535874(VS.85).aspx
function getXMLHttpRequest()
{
if (window.XMLHttpRequest) {
return new window.XMLHttpRequest;
}
else {
try {
return new ActiveXObject("MSXML2.XMLHTTP");
}
catch(ex) {
return null;
}
}
}
// this fn is invoked if IE
function IeBinFileReaderImpl(fileURL){
this.req = getXMLHttpRequest();
this.req.open("GET", fileURL, true);
this.req.setRequestHeader("Accept-Charset", "x-user-defined");
// my 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);
}
}
// call into VBScript utility fns
var rawBytes = IEBinaryToArray_ByteStr(binary);
var lastChr = IEBinaryToArray_ByteStr_Last(binary);
return rawBytes.replace(/[\s\S]/g,
function( match ) { return byteMapping[match]; }) + lastChr;
};
this.req.onreadystatechange = function(event){
if (that.req.readyState == 4) {
that.status = "Status: " + that.req.status;
//that.httpStatus = that.req.status;
if (that.req.status == 200) {
// this doesn't work
//fileContents = that.req.responseBody.toArray();
// this doesn't work
//fileContents = new VBArray(that.req.responseBody).toArray();
// this works...
var fileContents = convertResponseBodyToText(that.req.responseBody);
fileSize = fileContents.length-1;
if(that.fileSize < 0) throwException(_exception.FileLoadFailed);
that.readByteAt = function(i){
return fileContents.charCodeAt(i) & 0xff;
};
}
if (typeof callback == "function"){ callback(that);}
}
};
this.req.send();
}
// this fn is invoked if non IE
function NormalBinFileReaderImpl(fileURL){
this.req = new XMLHttpRequest();
this.req.open('GET', fileURL, true);
this.req.onreadystatechange = function(aEvt) {
if (that.req.readyState == 4) {
if(that.req.status == 200){
var fileContents = that.req.responseText;
fileSize = fileContents.length;
that.readByteAt = function(i){
return fileContents.charCodeAt(i) & 0xff;
}
if (typeof callback == "function"){ callback(that);}
}
else
throwException(_exception.FileLoadFailed);
}
};
//XHR binary charset opt by Marcus Granado 2006 [http://mgran.blogspot.com]
this.req.overrideMimeType('text/plain; charset=x-user-defined');
this.req.send(null);
}
转换码被提供Miskun。
效果很好。
我使用此方法从Javascript读取和提取zip文件,并且还在使用Javascript读取和显示EPUB文件的类中使用了该方法。性能非常合理。500kb文件大约需要半秒钟。
问题内容: 当尝试从ImageMagick子进程中读取Node.js中的数据时,它损坏了。 一个简单的测试用例如下: 我希望这等同于可以正确写入二进制文件的命令行。 最初存在maxBuffer选项太小并导致文件被截断的问题。增加该值之后,文件现在看起来比预期的要大一些,并且仍然损坏。来自stdout的数据是通过HTTP发送所必需的。 从ImageMagick stdout读取此数据的正确方法是什么
问题内容: 我正在尝试2天,以找到一种从数据库中检索一些图像的方法。它们被保存为二进制字符串(我在某个地方读过该术语,但坦率地说从未听说过)。 大多数图像都是格式化的,很容易获取并保存到文件中。但是我的问题是图像。由于某种原因,我当时无法显示。 现在,我正在使用一个简单的代码来获取图像并将其保存到文件中: 在和中都能正常工作,但是在尝试显示时格式不可读。 我已经发现但尚未解决的问题: http:/
问题内容: 在此URL中,我有一些Json数据。如何 使用该URL将数据获取到我的andorid应用程序。 我在Google中看到过引用。但是没有解决办法。 我是Andorid的新手。 请帮我。 问题答案: 做这个 : 步骤-1在您的gradle中导入排球库: 实现’com.android.volley:volley:1.1.0’ 然后在Java中编写以下代码:
问题内容: 已关闭 。这个问题需要更加集中。它当前不接受答案。 想改善这个问题吗? 更新问题,使其仅通过编辑此帖子来关注一个问题。 2年前关闭。 如何在MySQL中存储二进制数据? 问题答案: phpguy的答案是正确的,但我认为那里的其他细节存在很多混乱。 基本答案是在数据类型/属性域中。 BLOB 是Binary Large Object的缩写,该列数据类型专用于处理二进制数据。 请参见MyS
问题内容: 所以我一直在使用node.js(Js客户端和Android客户端)中的socket.io发送二进制数据时遇到麻烦。 没有太多信息,也没有: http://socket.io/blog/introducing-socket- io-1-0/ http://socket.io/get-started/chat/ 我需要使用套接字io发送我创建并填充的二进制数组。 他们给出的唯一代码如下:
我正在分析几个堆转储,并对从堆转储获取jvm参数的方法感兴趣。使用eclipse memory analyzer我可以很容易地获得系统属性和类路径,但我想知道是否有方法获得其他参数,如-xms-xmx等。