web-dev-qa-db-fra.com

Comment enregistrer et restaurer un objet File dans un stockage local

J'ai une application HTML5/javscript qui utilise 

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

capturer une image de la caméra. Comme mon application veut pouvoir être exécutée hors ligne, comment puis-je enregistrer l’objet File ( https://developer.mozilla.org/en-US/docs/Web/API/File ) dans le stockage local, de sorte peut être récupéré plus tard pour un téléchargement ajax?

Je suis en train de récupérer l'objet fichier à l'aide de ...

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

Je peux Stringifier et enregistrer l'objet, mais lorsque je le restaure, il n'est plus reconnu en tant qu'objet File et ne peut donc pas être utilisé pour récupérer le contenu du fichier.

J'ai l'impression que cela ne peut pas être fait, mais je suis ouvert aux suggestions. 

mon travail consiste à lire le contenu du fichier au moment de l’enregistrement et à enregistrer le contenu complet dans la mémoire locale. Cela fonctionne, mais consomme rapidement le stockage local car chaque fichier est une photo de 1 Mo plus.

30
pinoyyid

Vous ne pouvez pas sérialiser l'objet API de fichier. 

Non pas que cela aide avec le problème spécifique, mais ....__ Bien que je ne l'ait pas utilisé, si vous regardez ici il semble qu'il existe des moyens (bien que pas encore supportés par la plupart des navigateurs) données image hors ligne dans certains fichiers afin de les restaurer ultérieurement lorsque l'utilisateur est en ligne (et de ne pas utiliser le stockage local)

8

Voici une solution de contournement que j'ai obtenue avec le code ci-dessous. Je suis conscient qu'avec votre montage, vous avez parlé de stockage local mais je voulais vous dire comment j'ai mis en œuvre cette solution de contournement. J'aime mettre les fonctions sur le corps de sorte que même si la classe est ajoutée par la suite via AJAX, la commande "change" déclenchera toujours l'événement.

Voir mon exemple ici: http://jsfiddle.net/x11joex11/9g8NN/

Si vous exécutez l'exemple JSFiddle deux fois, vous verrez qu'il se souvient de l'image.

Mon approche utilise jQuery. Cette approche démontre également que l'image est réellement là pour prouver que cela a fonctionné.

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

Cette approche utilise les API du système de fichiers HTML5 pour lire l'image et la placer dans un nouvel objet img javascript. La clé ici est readAsDataURL. Si vous utilisez chrome inspector, vous remarquerez que les images sont stockées en encodage base64.

Le lecteur est asynchrone, c'est pourquoi il utilise la fonction de rappel onload. Veillez donc à ce que tout code important nécessitant l'image soit à l'intérieur de onLoad, sinon vous risquez d'obtenir des résultats inattendus. 

12
Joseph Astrahan

Convertissez-le en base64, puis enregistrez-le.

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

Vous pouvez utiliser cette lib: 

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

alors faites quelque chose de semblable à ceci: 

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

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

une autre solution consisterait à utiliser json (je préfère cette méthode) using: 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
Philip G

Je ne pense pas qu'il existe un moyen direct de Stringify, puis de désérialiser l'objet string dans l'objet de votre intérêt. Mais pour contourner le problème, vous pouvez stocker les chemins des images dans votre stockage local et charger les images en récupérant l'URL des images. Les avantages seraient, vous ne manquerez jamais d'espace de stockage et vous pouvez stocker 1000 fois plus de fichiers là-bas. Enregistrer une image ou tout autre fichier sous forme de chaîne dans une mémoire de stockage locale n'est jamais une sage décision .. 

1

créer un objet sur la portée globale 

exp: var attmap = new Object();

une fois la sélection de fichier terminée, placez vos fichiers dans la variable attmap ci-dessous,

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

Ensuite, vous pouvez l'envoyer au contrôleur via une entrée masquée ou etc. et l'utiliser après la désérialisation.

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

Vous pouvez créer vos fichiers avec ces valeurs dans une boucle for, etc.

EncodingUtil.base64Decode(CurrentMapValue);

FYI: Cette solution couvrira également la sélection de plusieurs fichiers

0
umithuckan