Желаемый будущий подход для хранения вещей на стороне клиента в веб-браузерах использует 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, так что играйте сейчас!