前几天,我们写了一篇关于如何在 localStorage 中保存图像和文件的文章,文章主要介绍了如何利用现有的功能。但是,localStorage 会带来一些性能问题,我们会在以后的博客中详细介绍,目前我们更希望利用 IndexedDB。在这里,我会指导你如何在 IndexedDB 中存储图像和文件,然后通过 ObjectURL 展示它们。
总体方法
首先,让我们谈谈我们将采取哪些步骤来创建一个 IndexedDB 数据库,将文件保存到其中,然后将其读取出来并在页面中显示。
- 创建或打开数据库。
- 创建一个 objectStore(如果它不存在)。
- 检索图像文件作为 blob。
- 启动数据库事务。
- 将该 blob 保存到数据库中。
- 读取已保存的文件并创建 ObjectURL,然后将其设置为页面中图像元素的 src 属性。
创建代码
让我们分解执行此操作所需的所有代码部分。
创建或打开数据库。
// IndexedDB window.indexedDB = window.indexedDB || window.webkitIndexedDB || window.mozIndexedDB || window.OIndexedDB || window.msIndexedDB, IDBTransaction = window.IDBTransaction || window.webkitIDBTransaction || window.OIDBTransaction || window.msIDBTransaction, dbVersion = 1; /* Note: The recommended way to do this is assigning it to window.indexedDB, to avoid potential issues in the global scope when web browsers start removing prefixes in their implementations. You can assign it to a varible, like var indexedDB… but then you have to make sure that the code is contained within a function. */ // Create/open database var request = indexedDB.open("elephantFiles", dbVersion);
request.onsuccess = function (event) {
console.log(“成功创建/访问 IndexedDB 数据库”);
db = request.result;
db.onerror = function (event) {
console.log(“创建/访问 IndexedDB 数据库时出错”);
};
// Google Chrome 的临时解决方案,用于创建 objectStore。将被弃用
if (db.setVersion) {
if (db.version != dbVersion) {
var setVersion = db.setVersion(dbVersion);
setVersion.onsuccess = function () {
createObjectStore(db);
getImageFile();
};
}
else {
getImageFile();
}
}
else {
getImageFile();
}
}
// 备用方案。目前仅适用于最新版本的 Firefox
request.onupgradeneeded = function (event) {
createObjectStore(event.target.result);
};
此方法的预期用途是,当创建数据库或数据库版本号升高时,触发 onupgradeneeded
事件。目前,此方法仅在 Firefox 中受支持,但很快将扩展到其他 Web 浏览器。如果 Web 浏览器不支持此事件,则可以使用已弃用的 setVersion
方法并连接到其 onsuccess
事件。
创建一个 objectStore(如果它不存在)。
// Create an objectStore console.log("Creating objectStore") dataBase.createObjectStore("elephants");
在这里,你创建了一个 ObjectStore,用于存储你的数据(在我们的例子中是文件),创建后无需重新创建,只需更新其内容即可。
检索图像文件作为 blob。
// Create XHR and BlobBuilder var xhr = new XMLHttpRequest(), blob; xhr.open("GET", "elephant.png", true); // Set the responseType to blob xhr.responseType = "blob"; xhr.addEventListener("load", function () { if (xhr.status === 200) { console.log("Image retrieved"); // File as response blob = xhr.response; // Put the received blob into IndexedDB putElephantInDb(blob); } }, false); // Send XHR xhr.send();
这段代码直接以 blob
的形式获取文件的内容。目前,此功能仅在 Firefox 中受支持。
收到整个文件后,将 blob 发送到函数以将其存储在数据库中。
启动数据库事务。
// Open a transaction to the database var transaction = db.transaction(["elephants"], IDBTransaction.READ_WRITE);
要开始向数据库写入内容,你需要使用 objectStore 名称和要执行的操作类型(在本例中为读取和写入)启动一个事务。
将该 blob 保存到数据库中。
// Put the blob into the dabase transaction.objectStore("elephants").put(blob, "image");
一旦事务到位,你就可以获取所需 objectStore 的引用,然后将你的 blob 放入其中并为其指定一个键。
读取已保存的文件并创建 ObjectURL,然后将其设置为页面中图像元素的 src 属性。
// Retrieve the file that was just stored transaction.objectStore("elephants").get("image").onsuccess = function (event) { var imgFile = event.target.result; console.log("Got elephant!" + imgFile); // Get window.URL object var URL = window.URL || window.webkitURL; // Create and revoke ObjectURL var imgURL = URL.createObjectURL(imgFile); // Set img src to ObjectURL var imgElephant = document.getElementById("elephant"); imgElephant.setAttribute("src", imgURL); // Revoking ObjectURL URL.revokeObjectURL(imgURL); };
使用相同的事务获取刚刚存储的图像文件,然后创建 ObjectURL 并将其设置为页面中图像的 src
属性。
同样地,这也可以是一个 JavaScript 文件,你将其附加到 script
元素,然后它会解析 JavaScript 代码。
完整的代码
这是完整的可运行代码。
(function () { // IndexedDB var indexedDB = window.indexedDB || window.webkitIndexedDB || window.mozIndexedDB || window.OIndexedDB || window.msIndexedDB, IDBTransaction = window.IDBTransaction || window.webkitIDBTransaction || window.OIDBTransaction || window.msIDBTransaction, dbVersion = 1.0; // Create/open database var request = indexedDB.open("elephantFiles", dbVersion), db, createObjectStore = function (dataBase) { // Create an objectStore console.log("Creating objectStore") dataBase.createObjectStore("elephants"); }, getImageFile = function () { // Create XHR and BlobBuilder var xhr = new XMLHttpRequest(), blob; xhr.open("GET", "elephant.png", true); // Set the responseType to blob xhr.responseType = "blob"; xhr.addEventListener("load", function () { if (xhr.status === 200) { console.log("Image retrieved"); // Blob as response blob = xhr.response; // Put the received blob into IndexedDB putElephantInDb(blob); } }, false); // Send XHR xhr.send(); }, putElephantInDb = function (blob) { console.log("Putting elephants in IndexedDB"); // Open a transaction to the database var transaction = db.transaction(["elephants"], IDBTransaction.READ_WRITE); // Put the blob into the dabase transaction.objectStore("elephants").put(blob, "image"); // Retrieve the file that was just stored transaction.objectStore("elephants").get("image").onsuccess = function (event) { var imgFile = event.target.result; console.log("Got elephant!" + imgFile); // Get window.URL object var URL = window.URL || window.webkitURL; // Create and revoke ObjectURL var imgURL = URL.createObjectURL(imgFile); // Set img src to ObjectURL var imgElephant = document.getElementById("elephant"); imgElephant.setAttribute("src", imgURL); // Revoking ObjectURL URL.revokeObjectURL(imgURL); }; }; request.onerror = function (event) { console.log("Error creating/accessing IndexedDB database"); }; request.onsuccess = function (event) { console.log("Success creating/accessing IndexedDB database"); db = request.result; db.onerror = function (event) { console.log("Error creating/accessing IndexedDB database"); }; // Interim solution for Google Chrome to create an objectStore. Will be deprecated if (db.setVersion) { if (db.version != dbVersion) { var setVersion = db.setVersion(dbVersion); setVersion.onsuccess = function () { createObjectStore(db); getImageFile(); }; } else { getImageFile(); } } else { getImageFile(); } } // For future use. Currently only in latest Firefox versions request.onupgradeneeded = function (event) { createObjectStore(event.target.result); }; })();
Web 浏览器支持
- IndexedDB
- 在 Firefox 和 Google Chrome 中已支持很长时间(多个版本之前)。计划在 IE10 和未来版本的 Opera 中支持。Safari 的情况尚不清楚。
- onupgradeneeded
- 在最新版本的 Firefox 中受支持。计划很快在 Google Chrome 中支持,并有望在 IE10 和未来版本的 Opera 中支持。Safari 的情况尚不清楚。
- 在 IndexedDB 中存储文件
- 在 Firefox 11 及更高版本中受支持。计划在 Google Chrome 中支持。IE10 有望支持此功能。Safari 和 Opera 的情况尚不清楚。
- XMLHttpRequest Level 2
- 在 Firefox 和 Google Chrome 中已支持很长时间,Safari 5+ 也支持,计划在 IE10 和 Opera 12 中支持。
- responseType “blob”
- 目前仅在 Firefox 中受支持。很快将在 Google Chrome 中支持,并计划在 IE10 和 Opera 12 中支持。Safari 的情况尚不清楚。
演示和代码
我已经创建了一个 使用 IndexedDB 和在其中保存图像和文件的演示,你可以在其中看到所有操作。确保使用任何开发者工具检查图像的元素,查看其 src
属性的值。还要确保检查 console.log 消息以跟踪操作。
关于 在 IndexedDB 中存储文件的代码,你也可以在 GitHub 上找到,赶快去试一试吧!
关于 Robert Nyman [荣誉编辑]
Mozilla Hacks 的技术布道者和编辑。关于 HTML5、JavaScript 和开放网络发表演讲和博客文章。Robert 坚信 HTML5 和开放网络,自 1999 年以来一直在从事网页前端开发工作,曾在瑞典和纽约市工作。他也会定期在 http://robertnyman.com 上发表博客文章,喜欢旅行和结识新朋友。
30 条评论