Подтвердить что ты не робот

Как сохранить и восстановить объект File в локальном хранилище

У меня есть приложение HTML5/javscript, которое использует

<input type="file" accept="image/*;capture=camera" onchange="gotPhoto(this)">

захватить изображение с камеры. Поскольку мое приложение хочет, чтобы его можно было запускать в автономном режиме, как сохранить объект File (https://developer.mozilla.org/en-US/docs/Web/API/File) в локальном хранилище, чтобы его можно было извлечь позже для загрузки AJAX?

Я хватаю объект файла с помощью...

function gotPhoto(element) { 
     var file = element.files[0];
     //I want to save 'file' to local storage here :-(
}

Я могу Stringify объекта и сохранить его, но когда я восстановлю его, он больше не распознается как объект File, и, следовательно, не может быть использован для захвата содержимого файла.

У меня есть ощущение, что это невозможно, но я открыт для предложений.

FWIW Мой обходной путь - прочитать содержимое файла во время хранения и сохранить все содержимое в локальном хранилище. Это работает, но быстро потребляет локальное хранилище, поскольку каждый файл занимает 1 МБ плюс фотографию.

4b9b3361

Ответ 1

Вы не можете сериализовать объект API файла.

Не то, чтобы это помогло с конкретной проблемой, но... Хотя я не использовал это, если вы посмотрите здесь, кажется, что есть способы (хотя в большинстве браузеров еще не поддерживается) для хранения офлайн данные изображения в некоторые файлы, чтобы восстановить их после того, как пользователь находится в сети (и не использовать localstorage)

Ответ 2

Вот обходной путь, с которым я работал с приведенным ниже кодом. Я знаю, что с вашим редактированием вы говорили о localStorage, но я хотел поделиться тем, как я действительно реализовал этот метод обхода. Мне нравится размещать функции на теле, так что, даже если класс добавляется после AJAX, команда "change" по-прежнему вызывает событие.

См. мой пример здесь: http://jsfiddle.net/x11joex11/9g8NN/

Если вы дважды запускаете пример JSFiddle, вы увидите, что он запоминает изображение.

В моем подходе используется jQuery. Этот подход также демонстрирует, что изображение действительно там, чтобы доказать, что оно сработало.

HTML:

<input class="classhere" type="file" name="logo" id="logo" />
<div class="imagearea"></div>

JS:

$(document).ready(function(){
  //You might want to do if check to see if localstorage set for theImage here
  var img = new Image();                
  img.src = localStorage.theImage;

  $('.imagearea').html(img);

  $("body").on("change",".classhere",function(){
      //Equivalent of getElementById
      var fileInput = $(this)[0];//returns a HTML DOM object by putting the [0] since it really an associative array.
      var file = fileInput.files[0]; //there is only '1' file since they are not multiple type.

      var reader = new FileReader();
      reader.onload = function(e) {
           // Create a new image.
           var img = new Image();

           img.src = reader.result;
           localStorage.theImage = reader.result; //stores the image to localStorage
           $(".imagearea").html(img);
       }

       reader.readAsDataURL(file);//attempts to read the file in question.
    });
});

В этом подходе используется API-интерфейс файловой системы HTML5, чтобы прочитать изображение и поместить его в новый объект javascript img. Ключевым здесь является readAsDataURL. Если вы используете инспектор хрома, вы заметите, что изображения хранятся в кодировке base64.

Читатель является асинхронным, поэтому он использует функцию обратного вызова onload. Поэтому убедитесь, что какой-либо важный код, требующий изображения, находится внутри onLoad, иначе вы можете получить неожиданные результаты.

Ответ 3

Преобразуйте его в base64 и затем сохраните.

function gotPhoto(element) {
var file = element.files[0];
var reader = new FileReader()
reader.onload = function(base64) {
localStorage["file"] = base64;
}
reader.readAsDataURL(file);
}
// Saved to localstorage
function getPhoto() {
var base64 = localStorage["file"];
var base64Parts = base64.split(",");
var fileFormat = base64Parts[0].split(";")[1];
var fileContent = base64Parts[1];
var file = new File([fileContent], "file name here", {type: fileFormat});
return file;
}
// Retreived file object

Ответ 4

Вы можете использовать этот lib:

https://github.com/carlo/jquery-base64

затем сделайте что-то похожее на это:

//Set file
var baseFile = $.base64.encode(fileObject);
window.localStorage.setItem("file",basefile);

//get file
var outFile = window.localStorage.getItem("file");

другое решение будет использовать json (я предпочитаю этот метод) используя: http://code.google.com/p/jquery-json/

//Set file
window.localStorage.setItem("file",$.toJSON(fileobject));

//get file
var outFile = $.evalJSON(window.localStorage.getItem("file"));

Ответ 5

Я не думаю, что есть прямой способ для Stringify, а затем десериализовать строковый объект в интересующий объект. Но, как работа вокруг, вы можете хранить пути изображения в своем локальном хранилище и загружать изображения, получая URL-адрес для изображений. Преимущества были бы, у вас никогда не будет нехватки места для хранения, и вы можете хранить там в 1000 раз больше файлов. Сохранение изображения или любого другого файла в виде строки в локальном хранилище никогда не будет разумным решением.

Ответ 6

создать объект в глобальной области видимости

exp: var attmap = new Object();

после того, как вы закончили с выбором файла, поместите ваши файлы в переменную attmap, как показано ниже,

attmap[file.name] = attachmentBody;
JSON.stringify(attmap)

Затем вы можете отправить его в контроллер через скрытый ввод или т.д. И использовать его после десериализации.

(Map<String, String>)JSON.deserialize(attachments, Map<String,String>.class);

Вы можете создавать свои файлы с этими значениями в цикле for и т.д.

EncodingUtil.base64Decode(CurrentMapValue);

К вашему сведению: это решение также будет охватывать выбор нескольких файлов

Ответ 7

Вы могли бы сделать что-то вроде этого:

// fileObj = new File(); from file input
const buffer = Buffer.from(await new Response(fileObj).arrayBuffer());
const dataUrl = 'data:${fileObj.type};base64,${buffer.toString("base64")}';

localStorage.setItem('dataUrl', dataUrl);

тогда вы можете сделать:

document.getElementById('image').src = localStorage.getItem('dataUrl');