Например, предположим, что пользователь загружает в ваше веб-приложение очень большие изображения или медиафайлы. Когда они возвращаются, вы хотите, чтобы ваше приложение показывало то, что они ранее загрузили, но не может хранить фактические данные файла в LocalStorage, потому что данные слишком велики.
Можно ли сохранить объект File в LocalStorage, а затем перезагрузить файл через FileReader, когда пользователь вернется на страницу?
Ответы (3)
Это НЕ возможно с localStorage
. Данные, хранящиеся в localStorage
, должны быть одним из примитивных типов, которые могут быть сериализованы. Сюда не входит объект File
.
Например, это не будет работать так, как вы ожидаете:
var el = document.createElement('input');
el.type='file';
el.onchange = function(e) {
localStorage.file = JSON.stringify(this.files[0]);
// LATER ON...
var reader = new FileReader();
reader.onload = function(e) {
var result = this.result; // never reaches here.
};
reader.readAsText(JSON.parse(localStorage.f));
};
document.body.appendChild(el);
Решение состоит в том, чтобы использовать более мощный вариант хранения, например запись содержимого файла в файловую систему HTML5 или спрятать в IndexedDB.
Технически вы можете, если вам просто нужно сохранить небольшие файлы в localStorage.
Просто base64, и так как это строка... она удобна для локального хранения.
Я думаю, что localStorage имеет ограничение ~ 5 МБ. Строки base64 имеют довольно небольшой размер файла, поэтому это вполне осуществимый способ хранения небольших изображений. Если вы используете этот ленивый способ, недостатком является то, что вам придется помнить об ограничении в 5 МБ. Я думаю, что это может быть решением в зависимости от ваших потребностей.
Да, это возможно. Вы можете вставить в LocalStorage любую информацию о файле, которую хотите, при условии, что вы сериализуете его в один из поддерживаемых примитивных типов. Вы также можете сериализовать весь файл в LocalStorage и получить его позже, если хотите, но существуют ограничения на размер файла в зависимости от браузера.
Ниже показано, как добиться этого, используя два разных подхода:
(function () {
// localStorage with image
var storageFiles = JSON.parse(localStorage.getItem("storageFiles")) || {},
elephant = document.getElementById("elephant"),
storageFilesDate = storageFiles.date,
date = new Date(),
todaysDate = (date.getMonth() + 1).toString() + date.getDate().toString();
// Compare date and create localStorage if it's not existing/too old
if (typeof storageFilesDate === "undefined" || storageFilesDate < todaysDate) {
// Take action when the image has loaded
elephant.addEventListener("load", function () {
var imgCanvas = document.createElement("canvas"),
imgContext = imgCanvas.getContext("2d");
// Make sure canvas is as big as the picture
imgCanvas.width = elephant.width;
imgCanvas.height = elephant.height;
// Draw image into canvas element
imgContext.drawImage(elephant, 0, 0, elephant.width, elephant.height);
// Save image as a data URL
storageFiles.elephant = imgCanvas.toDataURL("image/png");
// Set date for localStorage
storageFiles.date = todaysDate;
// Save as JSON in localStorage
try {
localStorage.setItem("storageFiles", JSON.stringify(storageFiles));
}
catch (e) {
console.log("Storage failed: " + e);
}
}, false);
// Set initial image src
elephant.setAttribute("src", "elephant.png");
}
else {
// Use image from localStorage
elephant.setAttribute("src", storageFiles.elephant);
}
// Getting a file through XMLHttpRequest as an arraybuffer and creating a Blob
var rhinoStorage = localStorage.getItem("rhino"),
rhino = document.getElementById("rhino");
if (rhinoStorage) {
// Reuse existing Data URL from localStorage
rhino.setAttribute("src", rhinoStorage);
}
else {
// Create XHR, BlobBuilder and FileReader objects
var xhr = new XMLHttpRequest(),
blob,
fileReader = new FileReader();
xhr.open("GET", "rhino.png", true);
// Set the responseType to arraybuffer. "blob" is an option too, rendering BlobBuilder unnecessary, but the support for "blob" is not widespread enough yet
xhr.responseType = "arraybuffer";
xhr.addEventListener("load", function () {
if (xhr.status === 200) {
// Create a blob from the response
blob = new Blob([xhr.response], {type: "image/png"});
// onload needed since Google Chrome doesn't support addEventListener for FileReader
fileReader.onload = function (evt) {
// Read out file contents as a Data URL
var result = evt.target.result;
// Set image src to Data URL
rhino.setAttribute("src", result);
// Store Data URL in localStorage
try {
localStorage.setItem("rhino", result);
}
catch (e) {
console.log("Storage failed: " + e);
}
};
// Load blob as Data URL
fileReader.readAsDataURL(blob);
}
}, false);
// Send XHR
xhr.send();
}
})();