如何从Opera中的Javascript访问8位二进制数据?

时间:2012-07-01 18:43:53

标签: javascript xmlhttprequest opera xmlhttprequest-level2

此问题是this StackOverflow question about IE对Opera 12浏览器的扩展。

根问题是issue in geoxml3处理kmz(压缩的kml)文件。

Example that fails in Opera 12

正在使用modified version of ZipFile.complete.js

中的TypedArrays处理二进制数据

传输二进制文件后,在Opera 12中未正确填充Uint8Array,就像数据被导入为16位元素一样。

请求配置如下:

this.req.responseType = 'arraybuffer';
this.req.overrideMimeType('text/plain; charset=x-user-defined');

返回的值如下处理:

var fileContents = binStream.req.response;
binStream.length = fileContents.byteLength;
binStream.array = new Uint8Array(fileContents);

在Opera 12中填充前八个字节:

0x004B0050;给出十进制值4915280

但应该是:

0x4034B50;小数值67324752。

这在Firefox,Chrome和IE中正常运行(有解决方法)。

有谁知道我如何说服Opera 12正确填充Uint8Array?或者一个解决方法,以便它可以工作(某种方式将16位字节数组转换为8位字节数组,尽可能有效地丢弃不需要的高8位)?这是Opera 12中最近实现TypedArray / XmlHttpRequest的已知错误吗?

2 个答案:

答案 0 :(得分:8)

Opera 12.00引入了对responseType的支持;不幸的是,它有一个错误,意味着给定一个text/* MIME类型,你将文件最终作为16位字。它在12.01中修复,但最简单的解决方法是将覆盖类型设置为application/octet-stream。 (对于那些希望跟踪一个封闭的bug追踪者的人来说,这是CORE-46938。)

答案 1 :(得分:2)

这个“补丁”有效:

var fileContents = binStream.req.response;
binStream.length = fileContents.byteLength;
binStream.array = new Uint8Array(fileContents);

/* patch for Opera */
if (/opera/i.test(navigator.userAgent) && 
    // make sure it is still broken,
    // the first 4 bytes will contain the zip file signature
    // for the geoxml3 use case (so bytes 1 & 3 will not be 0)
    (binStream.array[1] == 0) && (binStream.array[3] == 0))
{    
    fixedArray = new Uint8Array(binStream.length/2);
    for (var i=0; i<binStream.length; i+=2) {
        fixedArray[i/2]=binStream.array[i];
    }
    binStream.array = fixedArray;
    binStream.length = binStream.length/2;
}
/* end patch for Opera */

有更有效的方法吗?有没有人知道如何在不进行浏览器特定测试的情况下做到这一点?

编辑:添加检查以确保行为仍然被破坏(如果它是一个错误并且已修复)。可能在一般情况下不起作用,但对于geoxml3用例,前4个字节将包含zip文件签名,如果它正常工作,则不会有高位字节的0。