Сохранение изображений на стороне клиента с использованием LocalStorage

LocalStorage API предоставляет разработчикам прямой доступ к хранилищу данных, которое можно использовать для хранения информации на стороне клиента. Это позволит ускорить рендеринг веб-приложений за счет уменьшения количества запросов к базе данных.

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

Шаг 1

Сначала создадим простой HTML-файл.

<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Upload Image</title>
</head>
<body>
    
</body>
</html>

Для загрузки изображений будем использовать input type="file". Мы применим к нему несколько стилевых свойств.

<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Upload Image</title>
</head>
<body>
    <div class="row">
    <div class="input_box">
       
        <label for="">
            <input type="file" id="myFile" size="50" onchange="uploadImage(event)">
        </label>
    </div>
    </div>
</body>
</html>

Данный элемент ввода я подписал на событие onchange, которое будет обрабатываться  функцией uploadImage(event).

Стилизуем input type="file":

<style>
		.row{
        	display: flex;
        }
        .input_box {
            position: relative;
            height: 75px;
            width: 50%;
            margin: 0 auto;
            background-color: cadetblue;
            cursor: pointer;
            overflow: hidden;
            text-align: center;
            -webkit-transition: background-color ease-in-out 150ms;
            transition: background-color ease-in-out 150ms;
        }

        .input_box input {
            width: 100%;
            height: 100%;
            opacity: 0;
            overflow: hidden;
            position: absolute;
      
        }

        .input_box label {
            display: -webkit-box;
            display: -ms-flexbox;
            display: flex;
            -webkit-box-align: center;
            -ms-flex-align: center;
            align-items: center;
            width: 100%;
            height: 100%;
            font-weight: 400;
            text-overflow: ellipsis;
            white-space: nowrap;
            cursor: pointer;
            overflow: hidden;
        }

        .input_box label::after {
            content: '+';
            font-family: 'Material Icons';
            position: absolute;
            font-size: 2.5rem;
            color: #e6e6e6;
            top: calc(50% - 2.5rem);
            left: calc(50% - 1.25rem);
            z-index: 0;
            line-height: 2;
        }

        .input_box label:hover{
            background-color: transparent;
            color: cadetblue;
        }
</style>

Шаг 2

Создадим функцию для загрузки изображений в localStorage на стороне клиента.

<script>
	function uploadImage(event)
    {
    	
    }
</script>

Шаг 3

Затем с помощью объекта FileReader мы сможем получить содержимое файла изображения в формате base64. После чего оно будет сохранено в localStorage с именем файла в качестве ключа.

Теперь LocalStorage имеет атрибуты ключа и значения. Ключом является имя файла, а содержимое изображения – значением.

  <script>
	  function uploadImage(event) {
            var reader = new FileReader();
            var name = event.target.files[0].name;
            reader.addEventListener("load", function () {
                if (this.result && localStorage) {
                    window.localStorage.setItem(name, this.result);
                } else {
                    alert();
                }
            });
            reader.readAsDataURL(event.target.files[0]);
        }
</script>

В приведенном выше примере сначала создается новый экземпляр объекта FileReader, после чего сохраняется имя файла в переменной name.

С помощью функции reader.readAsDataURL мы получаем содержимое файла. Функция reader.addEventListener сохраняет изображение локально.

В приведенной выше функции (в конструкции If) используется два условия. this.result проверяет, поддерживает ли браузер локальное хранилище или нет.

Чтобы поместить содержимое в хранилище, используется функция localstorage.setItem(). В нее мы передаем ключ и значение для его сохранения.

Шаг 4

Для реализации предварительного просмотра изображения добавим кнопку, при нажатии на которую сработает функция showImage().

 <div class="row">
        <div class="input_box">

            <label for="">
                <input type="file" id="myFile" size="50" onchange="uploadImage(event)">
            </label>

        </div>

        <button onclick="showImages()" style="justify-content: center;" class="btn btn-primary">
            Show Images
        </button>
    </div>

Шаг 5

Добавим стилей:

  .btn {
            padding: 16px 25px;
            border: 0;
            background-color: #444;
            color: white;
            border-radius: 50px;
            cursor: pointer;
            transition: .25s all;
            height: 50px;
            width: 30%;
            margin: 10px auto;
        }

        .btn:hover {
            transform: translateY(-2%);
            color: #444;
            background: transparent;
            border: 1px solid #444;
        }

        .btn:focus {
            outline: none;
        }

Чтобы функция showImage() работала, необходимо получить изображения из хранилища. Для этого используем функцию localstorage.getItem().

Для просмотра всех изображения применим функцию window.localstorage.length().

function showImages() {
	 for (let i = 0; i < window.localStorage.length; i++) {
   		let res = window.localStorage.getItem(window.localStorage.key(i));	
   }
}

Шаг 6

Затем сохраним в переменной res все изображения, которые нужно отобразить. Для вывода изображений создадим новый тег <img> с помощью функции Image().

function showImages() {
	for (let i = 0; i < window.localStorage.length; i++) {
   		let res = window.localStorage.getItem(window.localStorage.key(i));
        var image = new Image();
        image.src = res;
   }
}

Шаг 7

Для отображения созданных элементов используем функцию append(image). Создадим блок div с идентификатором preview.

<div id="preview">

</div>

Шаг 8

Теперь изменим код функции showImages():

function showImages() {
	for (let i = 0; i < window.localStorage.length; i++) {
   		let res = window.localStorage.getItem(window.localStorage.key(i));
        var image = new Image();
        image.src = res;
        document.body.append(image);
   }
}

Шаг 9

Зададим стили <img>:

 img{
     height: 250px;
     border-radius: 10px;
     box-shadow: 0 0 1.2rem rgba(0,0,0,.25); 
     margin: 10px;
    }

Но как только вы нажмете кнопку «Показать изображения», будет добавлен <img> с тем же изображением. Поэтому теперь необходимо проверить, существует ли этот тег.

function showImages() {
            var img = document.getElementById("img");

            var parentDiv = document.getElementById('preview');
            if (parentDiv.contains(img)) {
                parentDiv.prepend(img);
            } else if (parentDiv.contains(img) == false) {
                for (let i = 0; i < window.localStorage.length; i++) {
               let res = window.localStorage.getItem(window.localStorage.key(i));
                    var image = new Image();
                    image.src = res;
                    image.setAttribute('id', 'img');
                    parentDiv.append(image);
                }
            }

Теперь реализуем удаление изображения. Для этого потребуется кнопка, которую мы создадим с помощью createElement().

Шаг 10

Затем добавим вызов функции, которая принимает имя удаляемого изображения в качестве аргумента.

function showImages() {
            var img = document.getElementById("img");

            var parentDiv = document.getElementById('preview');
            if (parentDiv.contains(img)) {
                parentDiv.prepend(img);
            } else if (parentDiv.contains(img) == false) {
                for (let i = 0; i < window.localStorage.length; i++) {
               let res = window.localStorage.getItem(window.localStorage.key(i));
                    var image = new Image();
                     var button = document.createElement("button");
                    button.innerHTML = "Delete";
                    button.setAttribute('class' , 'deleteButton');
                    button.setAttribute('onclick',DeleteImage('${window.localStorage.key(i)}')`);
                    image.src = res;
                    image.setAttribute('id', 'img');
                    parentDiv.append(image);
                    parentDiv.append(button);
                }
            }

Теперь кнопка удаления отображается для каждого изображения. Добавим к ней стили deleteButton.

 .deleteButton{
            border: 0;
            background-color: rgb(236, 81, 81);
            color: white;
            border-radius: 50px;
            cursor: pointer;
            transition: .25s all;
            height: 50px;
            margin: 10px auto; 
        }

С помощью функции localstorage.removeItem можно удалить пару ключ и значение.

Мы реализовали наглядный пример сохранения изображений на стороне клиента с помощью localStorage.

Вадим Дворниковавтор-переводчик статьи «Storing Image to client-side using window local storage»

Пожалуйста, оставьте свои отзывы по текущей теме материала. Мы крайне благодарны вам за ваши комментарии, лайки, подписки, отклики, дизлайки!