Safari 10中的IndexedDB现在支持blob。这在桌面上工作正常,但iOS 10上的移动Safari会抛出错误:
UnknownError
有时合并:
TransactionInactiveError (DOM IDBDatabase Exception): Failed to store record in an IDBObjectStore:
The transaction is inactive or finished.
代码(缩短):
var indexedDB = window.indexedDB || window.webkitIndexedDB || window.mozIndexedDB || window.msIndexedDB,
READ_WRITE = IDBTransaction && IDBTransaction.READ_WRITE ? IDBTransaction.READ_WRITE : 'readwrite',
storeName = 'files',
db;
init: function() {
var request = indexedDB.open('mydb');
request.onerror = ...;
request.onupgradeneeded = function() {
db = request.result;
db.createObjectStore(storeName);
};
request.onsuccess = function() {
db = request.result;
};
},
save: function(id, data) {
var put = function(data) {
var objectStore = db.transaction([storeName], READ_WRITE).objectStore(storeName),
request = objectStore.put(data, id);
request.onerror = ...;
request.onsuccess = ...;
};
// not all IndexedDB implementations support storing blobs, only detection is try-catch
try {
put(data);
} catch(err) {
if (data instanceof Blob) {
Helpers.blobToDataURL(data, put);
}
}
}
在移动版Safari 10上.put()
不会像以前那样抛出,只会在异步错误回调中稍后抛出。
Base64字符串工作正常。
Mobile Safari中的错误还是我必须更改代码?
答案 0 :(得分:11)
遇到同样的问题。 Chrome 54和Safari 10在桌面上运行良好,但在Mobile Safari上,我在尝试将Blob存储到IndexedDB时遇到Unknown
错误。我可以确认这只是Mobile Safari上Blob的问题,而不是对API的误用。
幸运的是,ArrayBuffers工作正常。所以我改为下载图像:
xhr.open('GET', url, true);
xhr.responseType = 'arraybuffer';
然后将它们作为ArrayBuffers保存到IndexedDB中,并在将它们拉出以获取URL后将它们转换为Blob:
putRequest = objectStore.put(arrayBuffer, id);
putRequest.onsuccess = function(event) {
objectStore.get(id).onsuccess = function(event) {
var blob = new Blob([event.target.result], { type: 'image/jpeg'});
var URL = window.URL || window.webkitURL;
blobUrl = URL.createObjectURL(blob);
};
};
我宁愿不必像这样将ArrayBuffers转换为Blob,因为我认为存在性能损失。但它确实有效。
答案 1 :(得分:1)
这个错误在我看来就像你必须改变代码一样。该错误并不表示blob存在问题。该错误表明您在调用函数时遇到问题。为了更好地回答您的问题,您需要发布更多周围的代码。具体来说,显示创建事务的代码部分以及在事务上创建请求的位置。
编辑:首先,删除window.indexedDB的东西。其次,不要以你使用它的方式使用'db',因为这不起作用,db可能会在调用save时关闭。
function save(id, data) {
var openRequest = indexedDB.open(...);
openRequest.onerror = console;
openRequest.onsuccess = function(event) {
var db = openRequest.result;
// Open the transaction
var tx = db.transaction(storeName, 'readwrite');
var store = tx.objectStore(storeName);
// Immediately use the transaction
try {
var putRequest = tx.put(data, id);
putRequest.onerror = console;
} catch(error) {
console.log(error);
}
};
}
Edit2:附加说明:
前缀已被删除,只使用indexedDB,而不是mozIndexedDB或webkitIndexedDB等
已删除事务模式常量,使用'readonly'或'readwrite',或者什么都没有(默认为readonly)
我对你如何打电话request = transaction.put
感到有些困惑。据我所知,没有方法IDBTransaction.prototype.put,如规范https://w3c.github.io/IndexedDB/#idbtransaction中所示。我很困惑为什么Mozilla文档显示了transaction.put的一个例子。检查Chrome 55中的IDBTransaction原型并未显示put方法。
有IDBObjectStore.prototype.put。您的代码不应该在任何平台上工作,因为它是当前编写的。所以,如果它确实有效,我很惊讶。您应该只使用var store = transaction.objectStore('store'); store.put(obj);
之类的东西来调用物品商店。