Man*_*uel 5 javascript safari blob indexeddb
我有完整的代码,你可以在最后复制,这样你就可以检查这个问题。
特尔;博士: 我使用的是 Safari 13.1,并且在将 Blob 存储在 IndexedDB 中之后。如果我关闭浏览器,我只能直接通过对象存储访问这些 Blob,而不能通过该对象存储的某些索引访问。如何使用索引正确恢复 Blob?
可能是我做错了什么,但这似乎在谷歌浏览器中没有任何问题。我在 IndexedDB 对象存储中存储了一个 Blob。我的意图是稍后获取它,并使用 URL.createObjectURL(blob) 使 blob 的内容可下载。
如果我存储 Blob 并且没有关闭选项卡,我会尝试恢复它并创建一个 URL,它可以正常工作,并且 URL 可以工作。我取回 Blob 的方式无关紧要(直接或通过索引)。在示例中,我只有一个 Blob。如果我这样做objectStore.index('index1').getAll('foo')或objectStore.getAll()它有效。
但是如果我重新启动 Safari 并再次打开网页,现在我只能直接从 objectStore ( objectStore.getAll()) 中获取 Blob 。但是,如果我尝试从索引 (objectStore.index('idx').getAll(key) ) 中则 Blob 不起作用。我正确获取了所有对象,其余信息存储在对象存储中,但 Blob 不起作用,如果我创建一个 URL,我会得到一个 WebKitBlobResource 1. 错误。
这是一些示例代码。
如果数据库不存在,它会使用对象存储和索引创建它,并在其中存储一个 Blob。有两个按钮可以从该 blob 生成 URL,它们都可以正常工作。如果重新启动 Safari,则只有其中一个有效(直接获取 Blob 的那个),另一个使用索引从数据库中获取的 URL 返回不起作用的 URL。
<!DOCTYPE html>
<html>
<head>
<title>Bug retrieving blobs from database</title>
</head>
<body>
<button id="clear-btn">Clear</button>
<button id="retrieve-working">Retrieve working</button>
<button id="retrieve-not-working">Retrieve not working</button>
<script>
document.getElementById('clear-btn').addEventListener('click', () => {
db.close();
indexedDB.deleteDatabase('bug');
});
document.getElementById('retrieve-working').addEventListener('click', async () => {
const objs = await getAllWithoutIndex();
console.log('Objects retrieved without index which result in a correct URL', URL.createObjectURL(objs[0].blob));
});
document.getElementById('retrieve-not-working').addEventListener('click', async () => {
const objs = await getAll('foo-1');
console.log('Objects retrieved', URL.createObjectURL(objs[0].blob));
});
let db, created = false;
const dbrequest = indexedDB.open('bug');
dbrequest.addEventListener('upgradeneeded', (e) => {
const db = e.target.result;
const objs = db.createObjectStore('objectstore', {keyPath: 'id', autoIncrement: true});
objs.createIndex('index1', 'foo', {unique: false});
created = true;
console.log('Database did not exist, we just created it');
});
dbrequest.addEventListener('success', async (e) => {
db = e.target.result;
if (created) {
console.log('Storing one object');
const obj1 = await store({
foo: 'foo-1',
blob: new Blob([0], {type: 'text/plain'}),
}).catch(console.error);
console.log('Object stored', obj1);
}
console.log('Database already exists, now you can get the objects');
});
function store(obj) {
return new Promise((resolve, reject) => {
const transaction = db.transaction('objectstore', 'readwrite');
const objectStore = transaction.objectStore('objectstore');
const request = objectStore.put(obj);
request.addEventListener('success', (e) => obj.id = e.target.result);
transaction.addEventListener('complete', () => resolve(obj));
});
}
function getAll(foo) {
return new Promise((resolve, reject) => {
const objectStore = db.transaction('objectstore', 'readonly').objectStore('objectstore');
const request = objectStore.index('index1').getAll(foo);
request.addEventListener('success', (e) => resolve(e.target.result));
});
}
function getAllWithoutIndex() {
return new Promise((resolve, reject) => {
const objectStore = db.transaction('objectstore', 'readonly').objectStore('objectstore');
const request = objectStore.getAll();
request.addEventListener('success', (e) => resolve(e.target.result));
});
}
</script>
</body>
</html>
Run Code Online (Sandbox Code Playgroud)