Skip to content

Instantly share code, notes, and snippets.

@joshontheweb
Last active January 18, 2017 10:32
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save joshontheweb/b17cf65cd1f6c4753f353badc119df17 to your computer and use it in GitHub Desktop.
Save joshontheweb/b17cf65cd1f6c4753f353badc119df17 to your computer and use it in GitHub Desktop.
tests adding large chunked blobs to indexeddb
<html>
<body>
<div>
Starting Quota:
<span id="startingQuota"></span>
</div>
<div>
Blob Size:
<span id="blobSize"></span>
</div>
<h2>Save whole blob</h2>
<div>
Whole Blob Status:
<span id="wholeBlobStatus"></span>
</div>
<h2>Save chunked blob</h2>
<div>
Bytes Saved:
<span id="bytesSaved"></span>
</div>
<div>
Chunk Offset:
<span id="chunkOffset"></span>
</div>
<div>
Error:
<span id="error"></span>
</div>
<div>
Ending Quota:
<span id="endingQuota"></span>
</div>
<script>
var wholeBlobStatusEl = document.getElementById('wholeBlobStatus');
var startingQuotaEl = document.getElementById('startingQuota');
var bytesSavedEl = document.getElementById('bytesSaved');
var chunkOffsetEl = document.getElementById('chunkOffset');
var blobSizeEl = document.getElementById('blobSize');
var errorEl = document.getElementById('error');
var endingQuotaEl = document.getElementById('endingQuota');
var blobSize = (Math.pow(1024, 2) * 300) // 300MB
var f32Length = blobSize / 4;
var blob = new Blob([new Float32Array(f32Length)]);
var chunkByteLength = (Math.pow(1024, 2) * .5) // 524k
var totalBytesSavedToStore = 0;
var dbName = 'testDb';
var dbVersion = 1;
var storeName = 'testStore'
blobSizeEl.innerHTML = blob.size;
var db;
function initDb () {
var self = this;
return new Promise(function (resolve, reject) {
if (db) {
resolve(db);
} else {
var objectStores = [
{name: storeName, indexes: [{name: 'byteOffset', unique: true}]},
];
console.log('Connecting to DB: ' + dbName + ' Store: ' + storeName);
var request = indexedDB.open(dbName, dbVersion);
request.onerror = function (e) {
errorEl.innerHTML = e.target.error;
console.log('Error: ', e);
reject(e);
};
request.onblocked = function (e) {
errorEl.innerHTML = e.target.error;
console.log('Blocked: ', e);
reject(e);
}
request.onupgradeneeded = function (e) {
console.log('running open request onupgradeneeded');
var db = e.target.result;
console.log(storeName, db.objectStoreNames);
objectStores.forEach(function (store) {
if (!db.objectStoreNames.contains(store.name)) {
var objectStore = db.createObjectStore(store.name, {autoIncrement: true});
var indexes = store.indexes;
if (indexes){
indexes.forEach(function (index) {
objectStore.createIndex(index.name, index.name, index.options);
});
}
}
});
};
request.onsuccess = function (e) {
console.log('running open request onsuccess');
db = e.target.result;
db.onerror = function (e) {
errorEl.innerHTML = e.target.error;
}
db.onversionchange = function (e) {
console.log('Version Change');
var db = e.target
db.close();
}
db.onblocked = function (e) {
console.log('blocked');
}
resolve(db);
};
}
});
}
function add (data, cb) {
// insert *new* data only
try {
var transaction = db.transaction([storeName], "readwrite");
var store = transaction.objectStore(storeName);
var request = store.add(data);
transaction.onabort = function (e) {
console.log('TRANSACTION ABORTED', e);
cb(e.target.error);
}
transaction.oncomplete = function (e) {
console.log(e);
if (cb) cb(null, e);
}
transaction.onerror = function (e) {
if (cb) cb(e.target.error);
}
} catch (err) {
if (cb) cb(err);
}
}
function saveToStore (blobChunk, cb) {
console.log('saveBlobToStore');
var self = this;
initDb().then(function (db) {
var attrs = {
byteOffset: totalBytesSavedToStore,
byteLength: blobChunk.size,
totalByteLength: totalBytesSavedToStore + blobChunk.size,
blob: blobChunk
};
add(attrs, function (err) {
if (err) {
errorEl.innerHTML = err;
console.error(err);
if (cb) cb(err);
} else {
totalBytesSavedToStore += attrs.byteLength;
if (cb) cb(null, totalBytesSavedToStore);
}
});
});
}
function saveChunk (start, byteLength, blob) {
var end = start + byteLength;
var blobChunk = blob.slice(start, end);
if (start < blob.size) {
saveToStore(blobChunk, function (err, totalBytesSaved) {
if (err) throw err;
bytesSavedEl.innerHTML = totalBytesSaved;
chunkOffsetEl.innerHTML = end;
console.log('Chunk Start Offset: ', end);
console.log('Blob size: ', blob.size);
saveChunk(end, byteLength, blob);
});
} else {
errorEl.innerHTML = 'finished with no errors';
navigator.webkitTemporaryStorage.queryUsageAndQuota(function (used, total) {
endingQuotaEl.innerHTML = JSON.stringify({total: total, used: used, free: total - used});
});
clearDatabase();
}
}
function clearDatabase (cb) {
try {
var transaction = db.transaction([storeName], "readwrite");
var store = transaction.objectStore(storeName);
var request = store.clear();
transaction.oncomplete = function (e) {
if (cb) cb();
}
transaction.onerror = function (e) {
if (cb) cb(e.target.error);
}
} catch (err) {
if (cb) cb(err);
}
}
navigator.webkitTemporaryStorage.queryUsageAndQuota(function (used, total) {
startingQuotaEl.innerHTML = JSON.stringify({total: total, used: used, free: total - used});
});
// save whole blob
saveToStore(blob, function (err, totalBytesSaved) {
wholeBlobStatusEl.innerHTML = 'Whole blob saved successfully: ' + totalBytesSaved;
// clean up
clearDatabase(function (err) {
if (err) {
errorEl.innerHTML = err;
console.log(err);
return;
}
totalBytesSavedToStore = 0;
// start saving chunked blob
saveChunk(0, chunkByteLength, blob);
});
});
</script>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment