2017-03-07 76 views
2

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

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

我已经试过:

  • 我试图设置一个unique标志artwork指数,但第二首歌曲的插入之前和之后检查数据库的大小后(使用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对象不支持吗?

回答

3

即使IndexedDB支持存储Blob,但它不支持对Blob进行索引。可转位属性只能是字符串,数字,日期或数组< string |数字|日期>。如果没有,IndexedDB将默默无视地索引该特定对象。

此外,在您的示例代码中,您不是指艺术品表格,而是尝试将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)); 
    }); 
}; 

我也建议存储ArrayBuffer而非BLOB(因为无论如何,我们读的斑点成ArrayBuffer我的样品不显示,但你可以在computeHash()分成两个不同的功能 - 一个将blob读入ArrayBuffer并将另一个读入ArrayBuffer,如果存储ArrayBuffer而不是Blob,则在Safari和其他一些较旧版本的Firefox中会出现较少的错误。

备注:在IndexedDB 2.0中,ArrayBuffers是可索引的(但不是Blob仍然)。但是,我绝不会建议在任何数据库中索引这么大的值。更好的索引摘要。

+0

我还建议使用哈希码 – Josh

+0

我实际上*做*实现哈希方法存储艺术品在一个单独的商店(使用'SparkMD5'),但后来我想也许我不需要它,利用'IndexedDB'索引和唯一约束。但是,没想到'Blob's可能不被支持。 –

+0

是的我的示例代码,这是一个代码转移的错误。固定。 –