2017-03-07 56 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

是的我的示例代碼,這是一個代碼轉移的錯誤。固定。 –