首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >在IndexedDB中防止重复的Blob对象

在IndexedDB中防止重复的Blob对象
EN

Stack Overflow用户
提问于 2017-03-07 22:22:53
回答 1查看 1.2K关注 0票数 2

是否有内置解决方案来防止在Blob中的不同记录中重复使用IndexedDB对象?

假设我有一个音乐商店的模式:id, title, album, artwork,我想从同一张专辑中向这个商店添加2首歌曲(所以它们很可能拥有相同的艺术品资产)。是否有一种内置的方式来自动存储艺术品一次?

我尝试过的:

  • 我试图在unique索引中设置一个artwork标志,但是在插入第二首歌曲之前和之后(使用chrome://settings/cookies)检查数据库的大小之后,艺术品会被存储两次。
  • 然后,我尝试用相同的标志将艺术品存储在单独的存储区(只有idartwork作为模式),但这也不起作用。
代码语言:javascript
运行
复制
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对象中不支持它吗?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2017-03-07 23:49:07

尽管IndexedDB支持存储Blobs,但它不支持索引Blobs。可索引属性只能是string、number、Date类型,也可以是Array。如果不是,IndexedDB将默默地忽略该特定对象的索引。

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

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

代码语言:javascript
运行
复制
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));
    });
};

我还建议存储ArrayBuffer,而不是blob (因为无论如何,我们都会将blob读入ArrayBuffer。我的示例没有显示这一点,但是您可以将computeHash()分成两个不同的函数-一个将blob读入ArrayBuffer,另一个将其哈希。如果您存储的是ArrayBuffer而不是blob,那么Safari和其他旧版本的火狐就不会那么容易出错了。

附带注意:在IndexedDB 2.0中,ArrayBuffers是可索引的(但仍然不能索引)。但是,我绝不会建议在任何数据库中索引这么大的值。更好的办法是给文摘编索引。

票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/42659488

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档