Можно ли сохранить объект File в LocalStorage, а затем перезагрузить файл через FileReader, когда пользователь вернется на страницу?

Например, предположим, что пользователь загружает в ваше веб-приложение очень большие изображения или медиафайлы. Когда они возвращаются, вы хотите, чтобы ваше приложение показывало то, что они ранее загрузили, но не может хранить фактические данные файла в LocalStorage, потому что данные слишком велики.


person Ronald    schedule 28.05.2011    source источник
comment
Используете ли вы Java на стороне клиента в своем приложении?   -  person namuol    schedule 28.05.2011
comment
Это в JavaScript, а не в Java.   -  person Ronald    schedule 28.05.2011
comment
Вы знаете Firebase? Возможно, этот вопрос поможет вам. stackoverflow .com/questions/13955813/   -  person hernanvicente    schedule 07.12.2013


Ответы (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.

person ebidel    schedule 24.08.2011
comment
На самом деле это технически возможно и, возможно, даже является осуществимым решением, если изображения, которые вы сохраняете, имеют небольшой размер файла. Смотрите мой ответ. - person wle8300; 22.09.2015
comment
Этот ответ явно неверен. Смотрите мой ответ ниже, чтобы узнать о нескольких способах достижения этого. - person mac; 10.05.2016
comment
2019, возможное решение, см. заголовок stackoverflow.com/questions/19119040/ - person Yngvar Kristiansen; 13.03.2019

Технически вы можете, если вам просто нужно сохранить небольшие файлы в localStorage.

Просто base64, и так как это строка... она удобна для локального хранения.

Я думаю, что localStorage имеет ограничение ~ 5 МБ. Строки base64 имеют довольно небольшой размер файла, поэтому это вполне осуществимый способ хранения небольших изображений. Если вы используете этот ленивый способ, недостатком является то, что вам придется помнить об ограничении в 5 МБ. Я думаю, что это может быть решением в зависимости от ваших потребностей.

person wle8300    schedule 22.09.2015

Да, это возможно. Вы можете вставить в 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();
}
})();

Источник

person mac    schedule 17.08.2011