在 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。需要一点时间,但仍然是一个可行的解决方案:)
我在将二进制图像数据加载到简单图像元素时遇到严重问题。我编写了一个 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。需要一点时间,但仍然是一个可行的解决方案:)