Jak zapisać i przywrócić obiekt File w pamięci lokalnej

Mam aplikację HTML5 / javscript, która używa

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

Aby uchwycić obraz z kamery. Ponieważ moja aplikacja chce być uruchamiana w trybie offline, jak Mogę zapisać plik ( https://developer.mozilla.org/en-US/docs/Web/API/File ) obiekt w pamięci lokalnej, taki, że może być pobrany później do uploadu ajax?

Pobieram obiekt file z using ...

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

Mogę przeciągnąć obiekt i zapisać go, ale kiedy go przywrócę, nie jest on już rozpoznawany jako obiekt pliku, a zatem nie może być użyty do pobrania zawartości pliku.

Mam wrażenie, że nie da się tego zrobić, ale jestem otwarty na sugestie.

Fwiw moją pracą jest odczytywanie zawartości pliku w czasie przechowywania i zapisywanie pełnej zawartości w pamięci lokalnej. To działa, ale szybko zużywa pamięć lokalną, ponieważ każdy plik to 1MB Plus zdjęcie.

Author: pinoyyid, 2013-10-01

6 answers

Nie można serializować obiektu API pliku.

Nie to, że pomaga w konkretnym problemie, ale ... Chociaż nie używałem tego, jeśli spojrzysz tutaj wydaje się, że istnieją sposoby (choć nie są jeszcze obsługiwane przez większość przeglądarek), aby zapisać dane obrazu offline do niektórych plików, aby przywrócić je później, gdy użytkownik jest online (i nie używać localstorage)

 8
Author: George Mavritsakis,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-10-08 16:02:01

Oto obejście, które mam pracując z poniższym kodem. Zdaję sobie sprawę, że w swojej edycji mówiłeś o localStorage, ale chciałem podzielić się tym, jak faktycznie wdrożyłem to obejście. Lubię umieszczać funkcje na ciele tak, że nawet jeśli klasa zostanie dodana później przez AJAX, Komenda "change" nadal wywoła zdarzenie.

Zobacz mój przykład tutaj: http://jsfiddle.net/x11joex11/9g8NN/

Jeśli uruchomisz przykład JSFiddle dwa razy zobaczysz, że pamięta obraz.

Moje podejście używa jQuery. Takie podejście pokazuje również, że obraz jest rzeczywiście tam, aby udowodnić, że działa.

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's 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.
    });
});

To podejście wykorzystuje API systemu plików HTML5 do odczytu obrazu i umieszczenia go w nowym obiekcie img javascript. Kluczem jest readAsDataURL. Jeśli używasz chrome inspector, zauważysz, że obrazy są przechowywane w kodowaniu base64.

Czytnik jest asynchroniczny , jest to dlaczego używa funkcji zwrotnej onload. Upewnij się więc, że każdy ważny kod, który wymaga obrazu, znajduje się wewnątrz onLoad, w przeciwnym razie możesz uzyskać nieoczekiwane wyniki.

 12
Author: Joseph Astrahan,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-12-12 06:00:44

Przekonwertuj go do base64, a następnie zapisz.

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
 2
Author: The helpful coding genius,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-01-01 16:37:51

Możesz użyć tej lib:

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

To zrób coś podobnego:

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

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

Innym rozwiązaniem byłoby użycie json (wolę tę metodę) użycie: http://code.google.com/p/jquery-json/

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

//get file
var outFile = $.evalJSON(window.localStorage.getItem("file"));
 1
Author: Philip G,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-10-05 14:11:25

Myślę, że nie ma bezpośredniego sposobu na Stringify, a następnie deserializacji obiektu string do obiektu, który Cię interesuje. Ale jako obejście można zapisać ścieżki obrazów w pamięci lokalnej i załadować obrazy, pobierając adres URL dla obrazów. Zaletą byłoby to, że nigdy nie zabraknie miejsca na dysku i można tam przechowywać 1000 razy więcej plików.. Zapisanie obrazu lub innego pliku jako ciągu znaków w pamięci lokalnej nigdy nie jest mądrą decyzją..

 1
Author: Jashobanta Chakraborty,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-12-18 20:31:45

Tworzenie obiektu o zasięgu globalnym

exp: var attmap = new Object();

Po zakończeniu wyboru pliku umieść pliki w zmiennej attmap jak poniżej,

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

Następnie możesz wysłać go do kontrolera poprzez wejście ukryte lub itp. i użyj go po deserializacji.

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

Możesz tworzyć pliki z tymi wartościami w pętli for lub etc.

EncodingUtil.base64Decode(CurrentMapValue);

FYI: To rozwiązanie obejmie również wybór wielu plików

 0
Author: umithuckan,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-01-16 20:11:40