在 Cordova 项目的 Android 4.1 上,将二进制图像数据加载到图像失败

Loading binary image data to an image fails on Android 4.1 in Cordova Project

我在将二进制图像数据加载到简单图像元素时遇到严重问题。我编写了一个 cordova 应用程序(使用 Sencha touch),它按以下方式加载图像:

xhr.open('GET', imageUrl, true);
xhr.responseType = 'blob';

xhr.addEventListener('load', function () {
    if (xhr.status === 200) {
        // onload needed since Google Chrome doesn't support addEventListener for FileReader
        fileReader.onload = function (evt) {
            image.setSrc(evt.target.result);
        };
        // Load blob as Data URL
        fileReader.readAsDataURL(xhr.response);
    }
}, false);

在 Android 5 和 4.4(这些是我测试过的)上,它就像一个魅力。现在我 运行 它 Android 4.1 在 ASUS 平板电脑上并且 onload 回调没有被触发。当我在 readAsDataURL 函数中抛出一个 blob 时,至少触发了 onload 回调,但图像也没有显示任何图像:(

有没有人建议,失败可能是什么或者我做错了什么?

啊,我终于用下面的代码在 Android 4.1.1 (ASUS Tablet) 上运行了。另一个问题是,保存来自 xhr 的 arraybuffer 响应不能简单地序列化,所以我将这些东西转换为字符串。我还收到了 blob 考虑到,在某些系统上 Blob 对象根本不存在:

function arrayBufferToString(buf) {
    return String.fromCharCode.apply(null, new Uint8Array(buf));
};

function stringToArrayBuffer(str) {
    var buf = new ArrayBuffer(str.length*2); // 2 bytes for each char
    var bufView = new Uint8Array(buf);
    for (var i=0, strLen=str.length; i<strLen; i++) {
        bufView[i] = str.charCodeAt(i);
    }
    return buf;
};

function getBlob(content, type) {
    var blob = null;

    // Android 4 only has the deprecated BlobBuilder :-(
    try {
        blob = new Blob([content], {type: type});
    } catch(e) {
        window.BlobBuilder = window.BlobBuilder || window.WebKitBlobBuilder ||
        window.MozBlobBuilder || window.MSBlobBuilder;

        if (window.BlobBuilder)
        {
            var bb = new BlobBuilder();
            bb.append(content);
            blob = bb.getBlob(type);
        }
    }

    return blob;
};

cachedFile = getCachedFile(...); // not of interest here, I think :-)
if (cachedFile)
{
    callback.apply(this, [window.webkitURL.createObjectURL(getBlob(stringToArrayBuffer(cachedFile.data), 'image/jpeg'))]);
}
else {
    xhr.open('GET', imageUrl, true);
    xhr.responseType = 'arraybuffer';

    xhr.addEventListener('load', function () {
        if (xhr.status === 200) {
            cachedFile = {
                url: imageUrl,
                data: arrayBufferToString(xhr.response)
            };

            addCachedFile(cachedFile); // not of interest here, I think :-)

            callback.apply(this, [window.webkitURL.createObjectURL(getBlob(xhr.response, 'image/jpeg'))]);
        }
    }, false);
    // Send XHR
    xhr.send();
}

编辑: 只是做了一点改动,现在使用 Uint8Array Class 而不是 Uint16Array Class 因为我得到了错误:"RangeError: byte length of Uint16Array should be a multiple of 2".现在很好用了。

Edit2: 刚刚看到,由于使用了 Uint8Array,上述代码并非在所有情况下都有效。 Uint16Array.

现在我想我有一个可靠的解决方案:我使用 canvas 和此处的函数 http://appcropolis.com/blog/web-technology/javascript-encode-images-dataurl/ 将图像 url 响应的二进制文件转换为 base64。需要一点时间,但仍然是一个可行的解决方案:)