Хранение изображений и файлов с помощью IndexedDB
Однажды мы писали о том, как сохранять изображения и файлы в localStorage, речь шла о том прагматизме, который у нас есть сегодня. Тем не менее, localStorage имеет некоторые последствия для производительности — мы обсудим это в следующем сообщении в блоге — и желаемый подход в будущем — использовать IndexedDB. Здесь я покажу вам, как хранить изображения и файлы в IndexedDB, а затем отображать их через ObjectURL.
Эта статья переведена, оригинальный текст здесьStoring images and files in IndexedDB
Об авторе:Robert Nyman [Editor emeritus]
Technical Evangelist & Editor of Mozilla Hacks. Gives talks & blogs about HTML5, JavaScript & the Open Web. Robert is a strong believer in HTML5 and the Open Web and has been working since 1999 with Front End development for the web - in Sweden and in New York City. He regularly also blogs at robertnyman.com and loves to travel and meet people.
Общие шаги для хранения изображений и файлов с помощью IndexedDB
Во-первых, давайте поговорим о шагах, которые мы предпримем, чтобы создать базу данных IndexedDB, сохранить в ней файл, а затем прочитать его и отобразить на странице:
- 1. Создайте или откройте базу данных
- 2. Создайте хранилище объектов
- 3. Получить файлы изображений в виде больших двоичных объектов
- 4. Инициализировать транзакцию базы данных
- 5. Сохраните большой двоичный объект изображения в базе данных.
- 6. Считайте сохраненный файл и создайте из него ObjectURL и установите его как src элемента изображения на странице.
1. Создайте или откройте базу данных.
// 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("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.
2. Создайте хранилище объектов (если оно еще не существует)
// Create an objectStore
console.log("Creating objectStore")
dataBase.createObjectStore("elephants");
Здесь вы создаете ObjectStore, в котором будете хранить данные — или, в нашем случае, файлы — и после создания вам не нужно его воссоздавать, просто обновите его содержимое.
3. Получить файлы изображений в виде больших двоичных объектов
// 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. Когда весь файл получен, большой двоичный объект отправляется функции для сохранения его в базе данных.
4. Инициализировать транзакцию базы данных
// Open a transaction to the database
var transaction = db.transaction(["elephants"], IDBTransaction.READ_WRITE);
Чтобы начать запись в базу данных, вам нужно запустить транзакцию с именем objectStore и типом операции, которую вы хотите выполнить (в данном случае чтение и запись).
5. Сохраните большой двоичный объект изображения в базе данных.
// Put the blob into the dabase
transaction.objectStore("elephants").put(blob, "image");
Как только транзакция выполнена, вы получаете ссылку на желаемый объектный склад, затем помещаете в него свой большой двоичный объект и передаете ему ключ.
6. Считайте сохраненный файл и создайте из него 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, прикрепленный к элементу сценария, который затем будет анализировать код 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);
};
})();