Comment enregistrer une image sur localStorage et l'afficher sur la page suivante?

154

Donc, fondamentalement, je dois télécharger une seule image, l'enregistrer dans localStorage, puis l'afficher sur la page suivante.

Actuellement, je télécharge mon fichier HTML:

<input type='file' id="uploadBannerImage" onchange="readURL(this);" />

Qui utilise cette fonction pour afficher l'image sur la page

function readURL(input) 
{
    document.getElementById("bannerImg").style.display = "block";

    if (input.files && input.files[0]) {
        var reader = new FileReader();

        reader.onload = function (e) {
            document.getElementById('bannerImg').src =  e.target.result;
        }

        reader.readAsDataURL(input.files[0]);
    }
}

L'image est affichée instantanément sur la page pour que l'utilisateur puisse la voir. Il leur est ensuite demandé de remplir le reste du formulaire. Cette partie fonctionne parfaitement.

Une fois le formulaire rempli, ils appuient sur un bouton «Enregistrer». Une fois ce bouton enfoncé, j'enregistre toutes les entrées de formulaire sous forme de localStoragechaînes. J'ai besoin d'un moyen d'enregistrer également l'image en tant localStoragequ'élément.

Le bouton Enregistrer les dirigera également vers une nouvelle page. Cette nouvelle page affichera les données des utilisateurs dans un tableau, l'image étant en haut.

Si clair et simple, je dois enregistrer l'image localStorageune fois que le bouton `` Enregistrer '' est enfoncé, puis prêter l'image sur la page suivante à partir de localStorage.

J'ai trouvé des solutions comme ce violon et cet article sur moz: // a HACKS .

Bien que je sois toujours extrêmement confus sur la façon dont cela fonctionne, et que je n'ai vraiment besoin que d'une solution simple. Fondamentalement, j'ai juste besoin de trouver l'image via getElementByIDune fois que le bouton `` Enregistrer '' est enfoncé, puis de traiter et d'enregistrer l'image.

Fizzix
la source
2
Quel est le problème avec le stockage de reader.result dans localstorage comme cet exemple: jsfiddle.net/x11joex11/9g8NN ?
Trace le
Pour les personnes qui cherchent à stocker de grandes quantités de données sur localStorage, cette bibliothèque est assez sympa: pieroxy / lz-string: algorithme de compression basé sur LZ pour JavaScript
brasofilo
"Je n'ai vraiment besoin que d'une solution simple." Pas tout le monde?
Rodrigo le

Réponses:

213

À quiconque a également besoin de résoudre ce problème:

Tout d'abord, je saisis mon image avec getElementByIDet enregistre l'image en tant que Base64. Ensuite, j'enregistre la chaîne Base64 comme ma localStoragevaleur.

bannerImage = document.getElementById('bannerImg');
imgData = getBase64Image(bannerImage);
localStorage.setItem("imgData", imgData);

Voici la fonction qui convertit l'image en une chaîne Base64:

function getBase64Image(img) {
    var canvas = document.createElement("canvas");
    canvas.width = img.width;
    canvas.height = img.height;

    var ctx = canvas.getContext("2d");
    ctx.drawImage(img, 0, 0);

    var dataURL = canvas.toDataURL("image/png");

    return dataURL.replace(/^data:image\/(png|jpg);base64,/, "");
}

Ensuite, sur ma page suivante, j'ai créé une image avec un blanc srccomme ceci:

<img src="" id="tableBanner" />

Et directement lorsque la page se charge, j'utilise ces trois lignes suivantes pour obtenir la chaîne Base64 localStorageet l'appliquer à l'image avec le blanc que srcj'ai créé:

var dataImage = localStorage.getItem('imgData');
bannerImg = document.getElementById('tableBanner');
bannerImg.src = "data:image/png;base64," + dataImage;

Je l'ai testé dans plusieurs navigateurs et versions différents, et cela semble fonctionner assez bien.

Fizzix
la source
1
Gif n'est pas pris en charge, car gif n'est pas pris en charge par canvas.
Allen
16
Vous n'avez pas besoin de la fonction getBase64Image. Les URL de données sont déjà en base 64, donc lorsque vous appelez reader.readAsDataURL, l'e.target.result envoyé au gestionnaire reader.onload sera tout ce dont vous avez besoin.
James
3
Gardez à l'esprit qu'il existe une limite d'environ 5 Mo pour le stockage local / de session. Et la conversion d'une image binaire en une chaîne encodée en base 64 la rendra environ 30% plus grande. Cela ne fonctionnerait donc pas pour les images haute résolution.
Noel Abrahams
Pourquoi supprimez-vous la partie initiale de l'URL de données? Pour réduire la taille?
deostroll
3
Notez que vous devez d'abord avoir une image entièrement chargée (sinon vous finirez par avoir des images vides), donc dans certains cas, vous devrez encapsuler la gestion dans: bannerImage.addEventListener ("load", function () {});
YE
9

J'ai écrit une petite bibliothèque de 2,2kb d'image de sauvegarde dans localStorage JQueryImageCaching Usage:

<img data-src="path/to/image">
<script>
    $('img').imageCaching();
</script>
moledet
la source
2
2,2 kilo-octets est énorme pour quelque chose comme ça, et je suppose que cela ne tient même pas compte de la taille de jQuery lui-même. Je suggérerais de l'écrire sans jQuery, peut-être qu'il sera plus petit
ChrisBrownie55
1,74 KB selon gitbub
hakiko
6

Vous pouvez sérialiser l'image dans un URI de données. Il y a un tutoriel dans ce billet de blog . Cela produira une chaîne que vous pourrez stocker dans le stockage local. Ensuite, sur la page suivante, utilisez l'URI de données comme source de l'image.

Ray Wadkins
la source
0

"Notez que vous devez d'abord avoir une image entièrement chargée (sinon vous finirez par avoir des images vides), donc dans certains cas, vous devrez encapsuler la gestion dans: bannerImage.addEventListener (" load ", function () {}); - yuga 1 novembre 17 à 13:04 "

Ceci est extrêmement IMPORTANT. L'une des options que j'explore cet après-midi consiste à utiliser des méthodes de rappel javascript plutôt que des addEventListeners car cela ne semble pas non plus se lier correctement. Il est essentiel de préparer tous les éléments avant le chargement de la page SANS actualisation de la page.

Si quelqu'un peut développer cela, veuillez faire - comme dans, avez-vous utilisé un settimeout, une attente, un rappel ou une méthode addEventListener pour obtenir le résultat souhaité. Lequel et pourquoi?

Andrew Ellison Pembroke
la source
utilisez toujours un callback si vous le pouvez, et n'utilisez jamais un settimeout si vous pouvez l'éviter. De par sa conception, vous voulez que la chose se produise après la chose précédente, avec le moins de frais généraux possible. C'est exactement ce pour quoi les rappels sont conçus
Grayson
-2

J'ai rencontré le même problème, au lieu de stocker des images, qui finissent par déborder du stockage local, vous pouvez simplement stocker le chemin de l'image. quelque chose comme:

let imagen = ev.target.getAttribute('src');
arrayImagenes.push(imagen);
SebasCiB3R
la source