Желаемый будущий подход для хранения вещей на стороне клиента в веб-браузерах использует IndexedDB . Здесь я расскажу, как хранить изображения и файлы в IndexedDB, а затем представлю их через ObjectURL .
Общий подход
Во-первых, давайте поговорим о шагах, которые мы пройдем, чтобы создать базу данных IndexedDB, сохранить файл в нем, а затем прочитать его и представить на странице:
- Создать или открыть базу данных.
- Создать objectStore (если он еще не существует)
- Получить файл изображения в виде BLOB-объекта
- Инициировать транзакцию базы данных
- Сохранить этот блоб в базу данных
- Считайте этот сохраненный файл, создайте из него ObjectURL и установите его в качестве источника изображения на странице.
Создание кода
Давайте разберем все части кода, которые нам нужны для этого:
Создать или открыть базу данных.
// IndexedDB var indexedDB = window.indexedDB || window.webkitIndexedDB || window.mozIndexedDB || window.OIndexedDB || window.msIndexedDB, IDBTransaction = window.IDBTransaction || window.webkitIDBTransaction || window.OIDBTransaction || window.msIDBTransaction, dbVersion = 1; // Create/open database var request = indexedDB.open("elephantFiles", dbVersion); 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); };
Предполагаемый способ использовать это — инициировать событие onupgradeneeded, когда база данных создается или получает более высокий номер версии. В настоящее время это поддерживается только в Firefox, но скоро будет в других веб-браузерах. Если веб-браузер не поддерживает это событие, вы можете использовать устаревший метод setVersion и подключиться к его событию onsuccess.
Создать objectStore (если он еще не существует)
// Create an objectStore console.log("Creating objectStore") dataBase.createObjectStore("elephants");
Здесь вы создаете ObjectStore, в котором вы будете хранить свои данные — или, в нашем случае, файлы — и после их создания вам не нужно будет создавать его заново, просто обновите его содержимое.
Получить файл изображения в виде BLOB-объекта
// Create XHR 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();
Этот код получает содержимое файла в виде двоичного объекта напрямую. В настоящее время это поддерживается только в Firefox.
Получив весь файл, вы отправляете BLOB-объект в функцию для сохранения его в базе данных.
Инициировать транзакцию базы данных
// Open a transaction to the database var transaction = db.transaction(["elephants"], IDBTransaction.READ_WRITE);
Чтобы начать запись чего-либо в базу данных, вам нужно инициировать транзакцию с именем objectStore и типом действия, которое вы хотите выполнить — в этом случае чтение и запись.
Сохранить этот блоб в базу данных
// Put the blob into the dabase transaction.objectStore("elephants").put(blob, "image");
Как только транзакция будет выполнена, вы получите ссылку на нужный объектный магазин, а затем поместите в нее свой большой двоичный объект и дадите ему ключ.
Считайте этот сохраненный файл, создайте из него ObjectURL и установите его в качестве источника изображения на странице.
// 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, который вы прикрепили к элементу скрипта, и тогда он будет анализировать 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 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; console.log("Blob:" + blob); // 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 var put = 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); }; })();
Поддержка веб-браузера
- IndexedDB
Поддерживается с давних пор (несколько версий назад) в Firefox и Google Chrome. Планируется быть в IE10, неясно про Safari и Opera.
- onupgradeneeded
Поддерживается в последнем Firefox. Планируется скоро появиться в Google Chrome и, надеюсь, в IE10. Непонятно о Сафари и Опере.
- Хранение файлов в IndexedDB
Поддерживается в Firefox 11 и более поздних версиях. Планируется поддержка в Google Chrome. Надеюсь, IE10 его поддержит. Непонятно о Сафари и Опере.
- XMLHttpRequest Уровень 2
Safari 5+ давно поддерживается в Firefox и Google Chrome, планируется в IE10 и Opera 12.
- responseType «blob»
В настоящее время поддерживается только в Firefox. Скоро будет в Google Chrome и планируется в IE10. Непонятно о Сафари и Опере.
Демо и код
Я собрал демо с IndexedDB и сохранил в нем изображения и файлы, где вы сможете увидеть все это в действии. Обязательно используйте любой инструмент разработчика для проверки элемента на изображении, чтобы увидеть значение его атрибута src. Также обязательно проверьте сообщения console.log, чтобы выполнить действия.
Код для хранения файлов в IndexedDB также доступен на GitHub, так что играйте сейчас!