Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/google-chrome/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 在IndexedDB中防止重复Blob对象_Javascript_Google Chrome_Indexeddb_Dexie - Fatal编程技术网

Javascript 在IndexedDB中防止重复Blob对象

Javascript 在IndexedDB中防止重复Blob对象,javascript,google-chrome,indexeddb,dexie,Javascript,Google Chrome,Indexeddb,Dexie,是否有内置解决方案来防止IndexedDB中不同记录中重复的Blob对象 假设我有一个音乐商店的模式:id、title、album、artwork,我想将同一个专辑中的两首歌曲添加到此商店(因此它们很可能具有相同的artwork资产)。是否有一种内置的方式可以只自动存储一次艺术品 我所尝试的: 我试图在artwork索引中设置unique标志,但在插入第二首歌曲前后检查了数据库的大小(使用chrome://settings/cookies),艺术品存储两次 然后,我尝试用相同的标志将艺术品存储

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

假设我有一个音乐商店的模式:
id、title、album、artwork
,我想将同一个专辑中的两首歌曲添加到此商店(因此它们很可能具有相同的artwork资产)。是否有一种内置的方式可以只自动存储一次艺术品

我所尝试的:

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

  • 然后,我尝试用相同的标志将艺术品存储在一个单独的商店中(只有
    id
    artwork
    作为模式),但这也不起作用




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

即使IndexedDB支持存储Blob,它也不支持索引Blob。可索引属性只能是字符串、数字、日期或数组类型。如果不是,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));
    });
};
我还建议存储ArrayBuffer而不是blob(因为我们无论如何都会将blob读入ArrayBuffer。我的示例没有显示这一点,但您可以拆分computeHash()分为两个不同的函数,一个用于将blob读入ArrayBuffer,另一个用于散列。如果存储ArrayBuffer而不是blob,则在Safari和其他较早版本的firefox中,错误发生率会降低)


旁注:在IndexedDB 2.0中,ArrayBuffers是可索引的(但仍然不是水滴)。然而,我决不建议在任何数据库中索引如此大的值。更好的办法是为摘要编制索引。

我实际上实现了一种散列方法,用于将艺术品存储在单独的存储库中(使用
SparkMD5
),但后来我想也许我不需要它,利用了
IndexedDB
索引和独特的约束。但是,我不认为Blobs可能不受支持。是的,关于我的示例代码,这是一个代码传输错误。修正了。谢谢你周到的回答。我将按照您的建议存储
ArrayBuffer
s,而不是
Blob
s。
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));
    });
};