¿Cómo guardar una imagen en localStorage y mostrarla en la página siguiente?

154

Entonces, básicamente, necesito cargar una sola imagen, guardarla en localStorage y luego mostrarla en la página siguiente.

Actualmente, tengo mi archivo HTML cargado:

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

Que utiliza esta función para mostrar la imagen en la página

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

La imagen se muestra instantáneamente en la página para que el usuario la vea. Luego se les pide que completen el resto del formulario. Esta parte está funcionando perfectamente.

Una vez que se completa el formulario, presionan el botón "Guardar". Una vez que se presiona este botón, guardo todas las entradas de formulario como localStoragecadenas. Necesito una manera de guardar también la imagen como un localStorageelemento.

El botón Guardar también los dirigirá a una nueva página. Esta nueva página mostrará los datos de los usuarios en una tabla, con la imagen en la parte superior.

Tan simple y simple, necesito guardar la imagen localStorageuna vez que se presiona el botón 'Guardar' y luego prestar la imagen en la página siguiente localStorage.

Encontré algunas soluciones como este violín y este artículo en moz: // a HACKS .

Aunque todavía estoy extremadamente confundido sobre cómo funciona esto, y realmente solo necesito una solución simple. Básicamente, solo necesito encontrar la imagen getElementByIDuna vez que se presiona el botón 'Guardar', y luego procesar y guardar la imagen.

Fizzix
fuente
2
¿Qué hay de malo en almacenar reader.result en localstorage como este ejemplo: jsfiddle.net/x11joex11/9g8NN ?
Seguimiento del
Para las personas que buscan almacenar grandes cantidades de datos en localStorage, esta biblioteca es bastante agradable: pieroxy / lz-string: algoritmo de compresión basado en LZ para JavaScript
brasofilo
"Solo necesito una solución simple". ¿No todos?
Rodrigo

Respuestas:

213

A quien también necesite resolver este problema:

En primer lugar, tomo mi imagen getElementByIDy la guardo como Base64. Luego guardo la cadena Base64 como mi localStoragevalor.

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

Aquí está la función que convierte la imagen en una cadena 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,/, "");
}

Luego, en mi página siguiente, creé una imagen con un espacio en blanco srcasí:

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

Y directamente cuando se carga la página, uso estas tres líneas siguientes para obtener la cadena Base64 localStoragey aplicarla a la imagen con el espacio en blanco srcque creé:

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

Lo probé en bastantes navegadores y versiones diferentes, y parece funcionar bastante bien.

Fizzix
fuente
1
Gif no es compatible, porque el lienzo no admite gif.
Allen
16
No necesita la función getBase64Image. Las URL de datos ya son de base 64, por lo que cuando llame a reader.readAsDataURL, el resultado e.target.result enviado al lector reader.onload será todo lo que necesita.
James H. Kelly
3
Tenga en cuenta que hay un límite de aproximadamente 5 MB para el almacenamiento local / sesión. Y convertir una imagen binaria en una cadena codificada de base 64 lo hará aproximadamente un 30% más grande. Entonces esto no funcionaría para imágenes de alta resolución.
Noel Abrahams
¿Por qué quitas la parte inicial de la url de datos? Para reducir el tamaño?
deostroll el
3
Tenga en cuenta que primero debe tener la imagen completamente cargada (de lo contrario, terminaría teniendo imágenes vacías), por lo que en algunos casos necesitaría ajustar el manejo en: bannerImage.addEventListener ("load", function () {});
YE
9

Escribí una pequeña biblioteca de 2,2 kb de guardar imágenes en localStorage JQueryImageCaching Usage:

<img data-src="path/to/image">
<script>
    $('img').imageCaching();
</script>
moledet
fuente
2
2.2 Kilobytes es enorme para algo como esto, además, supongo que eso ni siquiera tiene en cuenta el tamaño de jQuery. Sugeriría escribirlo sin jQuery, tal vez sea más pequeño
ChrisBrownie55
1.74 KB según gitbub
hakiko
6

Puede serializar la imagen en un URI de datos. Hay un tutorial en esto publicación de blog . Eso producirá una cadena que puede almacenar en el almacenamiento local. Luego, en la página siguiente, use el uri de datos como fuente de la imagen.

Ray Wadkins
fuente
0

"Tenga en cuenta que primero debe tener la imagen completamente cargada (de lo contrario, terminaría teniendo imágenes vacías), por lo que en algunos casos necesitaría ajustar el manejo en: bannerImage.addEventListener (" load ", function () {}); - yuga 01 de noviembre de 17 a 13:04 "

Esto es extremadamente IMPORTANTE. Una de las opciones que estoy explorando esta tarde es usar métodos de devolución de llamada de JavaScript en lugar de addEventListeners, ya que tampoco parece vincularse correctamente. Preparar todos los elementos antes de cargar la página SIN una actualización de la página es fundamental.

Si alguien puede ampliar esto, haga lo siguiente: ¿utilizó un tiempo de espera establecido, una espera, una devolución de llamada o un método addEventListener para obtener el resultado deseado? ¿Cuál y por qué?

Andrew Ellison Pembroke
fuente
use siempre una devolución de llamada si puede, y nunca use un tiempo de espera establecido si puede evitarlo. Por diseño, desea que suceda después de lo anterior, con la menor sobrecarga posible. Esto es exactamente para lo que están diseñadas las devoluciones de llamada
Grayson
-2

Se me ocurrió el mismo problema, en lugar de almacenar imágenes, que finalmente desbordan el almacenamiento local, solo puede almacenar la ruta a la imagen. algo como:

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