Chrome 防止IndexedDB中的重复Blob对象

yshpjwxd  于 2023-06-03  发布在  Go
关注(0)|答案(1)|浏览(127)

是否有一个内置的解决方案来防止IndexedDB中不同记录中的重复Blob对象?
假设我有一个音乐商店的模式:id, title, album, artwork,我想添加2首歌曲从同一张专辑到这个商店(所以他们最有可能有相同的艺术品资产)。是否有一个 * 内置 * 的方式来自动存储艺术品只有一次?

    • 我尝试过的:**
  • 我尝试在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对象中不支持它吗?

nhaq1z21

nhaq1z211#

尽管IndexedDB支持存储Blob,但它不支持对Blob进行索引。可索引属性只能是string、number、Date或Array <string类型|数|如果没有,IndexedDB将忽略对该特定对象的索引。
此外,在示例代码中,您没有引用artworks表,而是尝试单独放置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是可索引的(但Blobs仍然不是)。但是,我绝不建议在任何数据库中索引如此大的值。最好还是把文摘编入索引。

相关问题