javascript - 防止 IndexedDB 中出现重复的 Blob 对象

标签 javascript google-chrome indexeddb dexie

是否有内置解决方案可以防止 IndexedDB 中不同记录内出现重复的 Blob 对象?

假设我有一个音乐商店的架构:id、标题、专辑、艺术品,并且我想将同一专辑中的 2 首歌曲添加到该商店(因此它们很可能具有相同的内容)艺术品 Assets )。是否有一种内置方式可以自动将艺术品仅存储一次?

我尝试过的:

  • 我尝试在 artwork 索引中设置一个 unique 标志,但是在检查了插入第二首歌曲之前和之后的数据库大小之后(使用chrome://settings/cookies),艺术品被存储两次。

  • 然后,我尝试使用相同的标志将艺术品存储在单独的商店中(仅使用 idartwork 作为架构),但事实并非如此。也不工作。


var database = new Dexie('TheDatabase');
database.version(1).stores({artworks: '++id, &artwork'});

var dbArt = database.artworks;

var artworkBlob = getBlob(image);
dbArt.put(artworkBlob);

//later:
dbArt.put(artworkBlob);

我是否以任何方式滥用了unique标志? Blob 对象不支持它吗?

最佳答案

尽管 IndexedDB 支持存储 Blob,但它不支持索引 Blob。可索引属性只能是 string、number、Date 或 Array.如果没有,IndexedDB 将默默地忽略索引该特定对象。

此外,在示例代码中,您没有引用 arts 表,并且您尝试单独放置 blob,而不是放置包含 blob 属性的文档。

因此,您可以做的是计算 blob 内容的哈希/摘要,并将其存储为字符串,您可以使用唯一索引对其进行索引。

var dbArt = new Dexie('TheDatabase');
dbArt.version(1).stores({
    artworks: `
        ++id,
        title,
        album,
        &artworkDigest` // & = unique index of the digest
});

var artworkBlob = getBlob(image); // get it somehow...

// Now, compute hash before trying to put blob into DB
computeHash(artworkBlob).then(artworkDigest => {

    // Put the blob along with it's uniqely indexed digest
    return dbArt.artworks.put({
        title: theTitle,
        album: theAlbum,
        artwork: artworkBlob,
        artworkDigest: artworkDigest
    });
}).then(()=>{
    console.log("Successfully stored the blob");
}).catch(error => {
    // Second time you try to store the same blob, you'll
    // end up here with a 'ConstraintError' since the digest
    // will be same and conflict the uniqueness constraint.
    console.error(`Failed to store the blob: ${error}`);
});

function computeHash (blob) {
    return new Promise((resolve, reject) => {
        // Convert to ArrayBuffer
        var fileReader = new FileReader();
        fileReader.onload = () => resolve(filerReader.result);
        fileReader.onerror = () => reject(filerReader.error);
        fileReader.readAsArrayBuffer(blob);
    }).then (arrayBuffer => {
        // Compute Digest
        return crypto.subtle.digest("SHA-256", arrayBuffer);
    }).then (digest => {
        // Convert ArrayBuffer to string (to make it indexable)
        return String.fromCharCode.apply(
            null, new Uint8Array(digest));
    });
};

旁注:在 IndexedDB 2.0 中,ArrayBuffer 是可索引的(但 Blob 仍然不行)。但是,我永远不会建议在任何数据库中索引如此大的值。最好还是对摘要建立索引。

关于javascript - 防止 IndexedDB 中出现重复的 Blob 对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42659488/

相关文章:

javascript - ReactTransitionGroup 不适用于 React-redux 连接组件

javascript - Dexie modify() 失败但没有抛出错误

JavaScript 表操作

javascript - 如何检查是否从 jQuery 调用了特定的 id?

javascript - chrome 扩展 - 从串口读取

javascript - Chrome 平滑滚动和 requestAnimationFrame?

google-chrome - Chrome 63 - 不会显示带有变音符号的 SVG href 标识符

javascript - 在访问indexedDB或localStorage之前有什么方法可以检查授权吗?

JavaScript 函数总是返回 0

javascript - JQuery 两种形式切换,提交时显示正确的形式