Сохранение изображений на стороне клиента с использованием 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»