Как сохранить изображение в localStorage и отобразить его на следующей странице?

154

Итак, в основном мне нужно загрузить одно изображение, сохранить его в localStorage, а затем отобразить его на следующей странице.

В настоящее время я загружаю HTML-файл:

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

Который использует эту функцию для отображения изображения на странице

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

Изображение отображается мгновенно на странице для просмотра пользователем. Затем их просят заполнить оставшуюся форму. Эта часть работает отлично.

Когда форма заполнена, они нажимают кнопку «Сохранить». После нажатия этой кнопки все входные данные формы сохраняются в виде localStorageстрок. Мне нужен способ сохранить изображение как localStorageэлемент.

Кнопка сохранения также направит их на новую страницу. Эта новая страница отобразит данные пользователей в таблице, а изображение будет вверху.

Так просто и понятно, мне нужно сохранить изображение localStorageсразу после нажатия кнопки «Сохранить», а затем одолжить изображение на следующей странице localStorage.

Я нашел некоторые решения, такие как эта скрипка и эта статья в moz: // a HACKS .

Хотя я до сих пор не совсем понимаю, как это работает, и мне действительно нужно только простое решение. По сути, мне просто нужно найти изображение при getElementByIDнажатии кнопки «Сохранить», а затем обработать и сохранить изображение.

Fizzix
источник
2
Что не так с хранением reader.result в localalstorage, как в этом примере: jsfiddle.net/x11joex11/9g8NN ?
Трассировка
Для тех, кто хочет хранить большие объемы данных в localStorage, эта библиотека очень удобна
brasofilo
«Мне действительно нужно только простое решение». Не все?
Родриго

Ответы:

213

Для тех, кто также нуждается в решении этой проблемы:

Во-первых, я хватаю свое изображение getElementByIDи сохраняю его как Base64. Затем я сохраняю строку Base64 в качестве localStorageзначения.

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

Вот функция, которая преобразует изображение в строку 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,/, "");
}

Затем на моей следующей странице я создал изображение с таким бланком src:

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

И прямо при загрузке страницы я использую следующие три строки, чтобы получить строку Base64 localStorageи применить ее к изображению с srcсозданным мною пробелом :

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

Протестировал его в нескольких различных браузерах и версиях, и, похоже, он работает довольно хорошо.

Fizzix
источник
1
Gif не поддерживается, потому что GIF не поддерживается canvas.
Аллен
16
Вам не нужна функция getBase64Image. URL-адреса данных уже основаны на 64, поэтому при вызове reader.readAsDataURL e.target.result, отправленный обработчику reader.onload, будет всем, что вам нужно.
Джеймс Х. Келли
3
Имейте в виду, что для локального / сеансового хранилища существует ограничение в 5 МБ. А преобразование двоичного изображения в строку с кодировкой base 64 увеличит его примерно на 30%. Так что это не будет работать для изображений с высоким разрешением.
Ноэль Абрахамс
Почему вы удаляете начальную часть URL-адреса данных? Уменьшить размер?
deostroll
3
Обратите внимание, что сначала вам нужно полностью загрузить изображение (в противном случае заканчиваются пустыми изображениями), поэтому в некоторых случаях вам нужно будет обернуть обработку в: bannerImage.addEventListener ("load", function () {});
YE
9

Я написал небольшую библиотеку для сохранения изображения размером 2,2 Кбайт в LocalStorage JQueryImageCaching Использование:

<img data-src="path/to/image">
<script>
    $('img').imageCaching();
</script>
Моледет
источник
2
2.2 килобайта огромны для чего-то подобного, плюс я предполагаю, что это даже не учитывает размер самого jQuery. Я бы предложил написать его без jQuery, может быть, он будет меньше
ChrisBrownie55
1,74 КБ в соответствии с Gitbub
Хакико
6

Вы можете сериализовать изображение в URI данных. В этом посте есть учебник . Это создаст строку, которую вы можете хранить в локальном хранилище. Затем на следующей странице используйте данные URI в качестве источника изображения.

Рэй Уодкинс
источник
0

Msgstr "Обратите внимание, что сначала вам нужно полностью загрузить изображение (в противном случае заканчиваются пустыми изображениями), поэтому в некоторых случаях вам нужно будет обернуть обработку в: bannerImage.addEventListener (" load ", function () {}); - Юга 1 ноября '17 в 13:04 "

Это очень важно. Одна из опций, которую я изучаю сегодня днем, - это использование методов обратного вызова javascript, а не addEventListeners, поскольку, похоже, это тоже не связывает правильно. Подготовка всех элементов перед загрузкой страницы БЕЗ обновления страницы имеет решающее значение.

Если кто-то может расширить это, пожалуйста, сделайте, например, использовали ли вы settimeout, wait, callback или addEventListener для получения желаемого результата. Какой и почему?

Эндрю Эллисон Пемброк
источник
всегда используйте обратный вызов, если можете, и никогда не используйте settimeout, если вы можете избежать этого. По замыслу вы хотите, чтобы это произошло после предыдущего, с минимальными накладными расходами. Это именно то, для чего предназначены обратные вызовы
Грейсон
-2

У меня возникла та же проблема, вместо хранения изображений, которые в конечном итоге переполняют локальное хранилище, вы можете просто сохранить путь к изображению. что-то вроде:

let imagen = ev.target.getAttribute('src');
arrayImagenes.push(imagen);
SebasCiB3R
источник