Jak zapisać obraz w localStorage i wyświetlić go na następnej stronie?

154

Zasadniczo muszę przesłać pojedynczy obraz, zapisać go w localStorage, a następnie wyświetlić na następnej stronie.

Obecnie mam załadowany plik HTML:

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

Który używa tej funkcji do wyświetlenia obrazu na stronie

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

Obraz jest natychmiast wyświetlany na stronie, aby użytkownik mógł go zobaczyć. Następnie proszeni są o wypełnienie pozostałej części formularza. Ta część działa idealnie.

Po wypełnieniu formularza naciskają przycisk „Zapisz”. Po naciśnięciu tego przycisku zapisuję wszystkie dane wejściowe formularza jako localStorageciągi. Potrzebuję sposobu na zapisanie obrazu jako localStorageelementu.

Przycisk Zapisz również przekieruje ich na nową stronę. Ta nowa strona wyświetli dane użytkowników w tabeli, z obrazem u góry.

Tak prosty i prosty, że localStoragepo naciśnięciu przycisku „Zapisz” muszę zapisać obraz , a następnie wypożyczyć go na następnej stronie localStorage.

Znalazłem rozwiązania, takie jak to skrzypce i ten artykuł na moz: // a HACKS .

Chociaż nadal jestem bardzo zdezorientowany, jak to działa, i naprawdę potrzebuję tylko prostego rozwiązania. Po prostu muszę znaleźć obraz za pomocą getElementByIDprzycisku „Zapisz”, a następnie przetworzyć i zapisać obraz.

Fizzix
źródło
2
Co jest złego w przechowywaniu reader.result w localstorage, jak w tym przykładzie: jsfiddle.net/x11joex11/9g8NN ?
Śledź
Dla osób, które chcą przechowywać duże ilości danych w localStorage, ta biblioteka jest całkiem fajna: pieroxy / lz-string: algorytm kompresji oparty na LZ dla JavaScript
brasofilo
„Potrzebuję tylko prostego rozwiązania”. Czy nie wszyscy?
Rodrigo

Odpowiedzi:

213

Do każdego, kto również potrzebuje rozwiązania tego problemu:

Po pierwsze, pobieram obraz getElementByIDi zapisuję go jako Base64. Następnie zapisuję ciąg Base64 jako moją localStoragewartość.

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

Oto funkcja, która konwertuje obraz na ciąg 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,/, "");
}

Następnie na mojej następnej stronie utworzyłem obraz z pustym miejscem src:

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

I od razu po załadowaniu strony używam tych trzech kolejnych wierszy, aby pobrać ciąg Base64 z localStoragei zastosować go do obrazu z pustym, srcktóry utworzyłem:

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

Przetestowałem go w kilku różnych przeglądarkach i wersjach i wydaje się, że działa całkiem dobrze.

Fizzix
źródło
1
Gif nie jest obsługiwany, ponieważ format GIF nie jest obsługiwany przez Canvas.
Allen
16
Nie potrzebujesz funkcji getBase64Image. Adresy URL danych mają już bazę 64, więc po wywołaniu reader.readAsDataURL adres e.target.result wysłany do modułu obsługi reader.onload będzie wszystkim, czego potrzebujesz.
James H. Kelly
3
Pamiętaj, że istnieje limit około 5 MB dla pamięci lokalnej / sesji. Konwersja obrazu binarnego na ciąg zakodowany w standardzie 64 spowoduje, że będzie on o około 30% większy. Więc to nie zadziała dla obrazów o wysokiej rozdzielczości.
Noel Abrahams
Dlaczego usuwasz początkową część adresu URL? Aby zmniejszyć rozmiar?
deostroll
3
Zwróć uwagę, że najpierw musisz w pełni załadować obraz (w przeciwnym razie skończy się to na pustych obrazach), więc w niektórych przypadkach będziesz musiał opakować obsługę w: bannerImage.addEventListener ("load", function () {});
YE
9

Napisałem małą bibliotekę 2,2kb do zapisywania obrazu w localStorage JQueryImageCaching Usage:

<img data-src="path/to/image">
<script>
    $('img').imageCaching();
</script>
moledet
źródło
2
2.2 Kilobajtów jest ogromna jak na coś takiego, a myślę, że to nawet nie bierze pod uwagę rozmiaru samego jQuery. Proponuję pisać bez jQuery, może będzie mniejszy
ChrisBrownie55
1,74 KB według gitbub
hakiko
6

Możesz serializować obraz do identyfikatora URI danych. W tym poście na blogu znajduje się samouczek . Spowoduje to utworzenie ciągu, który można przechowywać w pamięci lokalnej. Następnie na następnej stronie użyj adresu URI danych jako źródła obrazu.

Ray Wadkins
źródło
0

„Zauważ, że najpierw musisz w pełni załadować obraz (w przeciwnym razie skończy się to na pustych obrazach), więc w niektórych przypadkach musisz opakować obsługę w: bannerImage.addEventListener (" load ", function () {}); - yuga 1 listopada 2017 o 13:04 "

To jest niezwykle WAŻNE. Jedną z opcji, które badam dziś po południu, jest użycie metod wywołania zwrotnego javascript zamiast addEventListeners, ponieważ to również nie wydaje się być poprawnie powiązane. Przygotowanie wszystkich elementów przed załadowaniem strony BEZ odświeżania strony jest krytyczne.

Jeśli ktokolwiek może to rozwinąć, zrób to - tak jak w, czy użyłeś settimeout, wait, callback lub metody addEventListener, aby uzyskać pożądany wynik. Który i dlaczego?

Andrew Ellison Pembroke
źródło
zawsze używaj oddzwaniania, jeśli możesz, i nigdy nie używaj ustawionego limitu czasu, jeśli możesz go uniknąć. Zgodnie z projektem chcesz, aby coś wydarzyło się po poprzedniej rzeczy, przy jak najmniejszym nakładzie pracy. Właśnie do tego są przeznaczone wywołania zwrotne
Grayson
-2

Wymyśliłem ten sam problem, zamiast przechowywać obrazy, które ostatecznie przepełniają lokalną pamięć, możesz po prostu zapisać ścieżkę do obrazu. coś jak:

let imagen = ev.target.getAttribute('src');
arrayImagenes.push(imagen);
SebasCiB3R
źródło