Comment puis-je sauvegarder et restaurer un objet fichier dans le stockage local

j'ai une application HTML5 / javscript qui utilise

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

pour capturer une image de caméra. Parce que mon application veut être exécutable hors ligne, Comment puis-je sauvegarder le fichier (https://developer.mozilla.org/en-US/docs/Web/API/File) objet dans le stockage local, de sorte qu'il peut être récupéré plus tard pour un téléchargement ajax?

je prends l'objet file depuis l'utilisation ...

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

je peux Stringifier l'objet et le sauver, mais quand je le restaure, il n'est plus reconnu comme un objet de fichier, et ne peut donc pas être utilisé pour saisir le contenu du fichier.

j'ai le sentiment que cela ne peut pas être fait, mais je suis ouvert aux suggestions.

fwiw mon travail consiste à lire le contenu du fichier au moment du stockage et à sauvegarder le contenu complet dans le stockage local. Cela fonctionne, mais consomme rapidement le stockage local puisque chaque fichier est une photographie de 1 Mo plus.

28
demandé sur pinoyyid 2013-10-01 18:36:24

6 réponses

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

non pas que cela aide avec le problème spécifique, mais ... Bien que je ne l'ai pas utilisé, si vous regardez ici il semble qu'il existe des moyens (bien que pas encore pris en charge par la plupart des navigateurs) pour stocker l'image en mode hors connexion de données à certains fichiers afin de les restaurer par la suite lorsque l'utilisateur est en ligne (et de ne pas utiliser localstorage)

8
répondu George Mavritsakis 2013-10-08 16:02:01

Voici une solution de contournement que j'ai obtenu en travaillant avec le code ci-dessous. Je sais qu'avec votre édition vous avez parlé de localStorage mais je voulais partager comment j'ai réellement mis en œuvre Cette solution de contournement. J'aime mettre les fonctions sur body de sorte que même si la classe est ajoutée par la suite via AJAX, la commande "change" déclenchera tout de même l'événement.

http://jsfiddle.net/x11joex11/9g8NN/

si vous exécutez l'exemple JSFiddle deux fois vous le verrez se souvient de l'image.

mon approche utilise jQuery. Cette approche démontre également que l'image est en fait là pour prouver qu'elle 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 L'API du système de fichiers HTML5 pour lire l'image et la mettre dans un nouvel objet javascript img. La clé ici est readAsDataURL. Si vous utilisez chrome inspector, vous remarquerez que les images sont stockées dans base64 encodage.

Le lecteur est Asynchrone, c'est pourquoi il utilise la fonction de rappel onload. Donc assurez-vous que tout code important qui nécessite l'image est à l'intérieur de l'onLoad ou vous pouvez obtenir des résultats inattendus.

12
répondu Joseph Astrahan 2013-12-12 06:00:44

Convertir en base64 et de l'enregistrer.

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
répondu The helpful coding genius 2017-01-01 16:37:51

Vous pouvez utiliser cette lib:

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

puis faire quelque chose de similaire à ceci:

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

//get file
var outFile = window.localStorage.getItem("file");
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
répondu Philip G 2013-10-05 14:11:25

Je ne pense pas qu'il y ait un moyen direct de Stringifier et ensuite de desérialiser l'objet string dans l'objet de votre intérêt. Mais comme un travail autour vous pouvez stocker les chemins d'image dans votre stockage local et charger les images en récupérant l'URL pour les images. Avantages seraient, vous ne manquerez jamais d'espace de stockage et vous pouvez stocker 1000 fois plus de fichiers.. Sauvegarder une image ou tout autre fichier sous forme de chaîne de caractères dans un espace de stockage local n'est jamais une décision judicieuse..

1
répondu Jashobanta Chakraborty 2013-12-18 20:31:45

créer un objet sur la portée globale

exp: var attmap = new Object();

après que vous avez terminé avec la sélection de fichier, mettez vos fichiers dans la variable attmap comme ci-dessous,

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

Ensuite, vous pouvez l'envoyer au contrôleur via l'entrée cachée ou etc. et les 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 ou etc.

EncodingUtil.base64Decode(CurrentMapValue);

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

0
répondu umithuckan 2018-01-16 20:11:40