Разбираемся с добавлением изображений к статьям с привязкой к базе данных.
Предыдущая статья: Блог на Svelte. Часть 6: Авторство, теги, пагинация и поддержка markdown
Загрузка изображений к статьям
Мы не будем реализовывать возможность добавлять изображения непосредственно посреди текста. В рамках этого гайда упростим себе задачу и сделаем выбор в пользу заглавных картинок без каких-либо иллюстраций в теле постов.
Настройка Supabase
Начать надо с дополнительной настройки базы данных. Дело в том, что мы будем все файлы изображений хранить в Supabase. Можно выбрать и стороннее хранилище, но конкретно в нашем случае Supabase более чем подходит, предоставляя бесплатно аж целый гигабайт под любые медиафайлы. К тому же мы уже умеем работать с этой БД и нам не составит труда адекватно реализовать все необходимые функции без надобности учить новые варианты взаимодействия с информацией.
Сначала открываем Supabase и переходим в раздел Storage. Внутри находим кнопку Create a new bucket и нажимаем на нее. Так создастся отдельное хранилище под файлы.
![]()
Назовем это хранилище pictures, так как здесь будут храниться изображения для всего и сразу. Делаем хранилище файлов публичным, переключив тумблер Make bucket public. Затем сохраняем получившийся bucket.
![]()
Затем ищем в разделе Storage пункты выдачи прав на управления данными. Все они сопровождаются кнопкой New policy. Жмем на нее.
![]()
В появившемся разделе выбираем Create a policy from a template.
Внутри можно выбрать один из шаблонов. Нам нужен тот, что дает право на внесение любых изменений в хранилище файлов. То есть первый вариант. Редактировать его не нужно.
![]()
Даже на следующем экране не надо вносить изменений, единственное, что нужно сделать, поставить галочку напротив пункта ALL.
![]()
На этом все. Теперь можно делать запросы к хранилищу файлов и не ловить в ответ ошибки из-за нехватки привилегий.
Кнопка добавления новых изображений
Следующий этап – загрузка изображений к статьям. Мы добавим соответствующий интерфейс в блок создания новой статьи. То есть в тот, где мы указываем название, пишем текст и выбираем теги. Поэтому редактировать будем файл NewPost.svelte.
Сначала открываем NewPost.svelte. Потом добавляем переменную file, чтобы хранить в ней элемент, отвечающий за загрузку изображения в браузер.
let file;
![]()
После этого создадим функцию загрузки новых изображений и дополним функцию создания поста, чтобы привязать название новой картинки к конкретному посту.
![]()
Осталось связать название загруженной картинки с нашей статьей.
Мы слегка модифицируем функцию добавления новых постов, чтобы установить связь между картинкой и статьей.
![]()
Теперь в базе данных Posts будет появляться еще и название картинки. По нему мы сможем находить нужное изображение и показывать его читателям. Это не самый элегантный способ, и на этапе рефакторинга мы его заменим на более простой алгоритм, но и такой вариант тоже возможен.
Не забудьте после этого добавить в html-блок input для загрузки файлов с привязкой к соответствующей переменной – <input bind:this={file} type="file" />
![]()
Интерфейсы для отображения существующих картинок
Мы научились загружать картинки. Теперь нужно научить сайт корректно подгружать изображение для статей и показывать их пользователю. В первую очередь мы будем генерировать изображение полностью самостоятельно. То есть создавать новый объект и подсоединять его к уже существующему элементу в верстке. Также мы рассмотрим и другой вариант добавления изображения при помощи одной лишь ссылки.
Начнем с отображения картинки в уже открытой статье.
![]()
Сначала просто добавляем переменную imageBlock. Это будет div, в котором мы отрисуем изображение из базы данных.
![]()
Потом этот div мы добавим в html-разметку:
<div bind:this={imageBlock}></div>
Теперь пишем функцию для добычи изображений из Supabase.
![]()
-
Создаем асинхронную функцию getImage: const getImage = async ( ) => { }
-
В тело добавляем запрос ко всему списку изображений (обращаясь к набору pictures, созданному нами в Supabase): const { data } = await supabase.storage.from('pictures').list()
-
Ищем среди изображений имя того, что соответствует названию нашей статьи. Воспользуемся для этого методом find для поиска по массивам: const imageName = data.find(e => e.name.includes(title))
-
Также добавляем сюда расширение тем же методом, что и в предыдущей функции: const imageExt = imageName.name.split('.').pop()
- Делаем еще один запрос к базе данных, чтобы запросить публичную ссылку на изображение: const { publicURL, error } = supabase.storage.from('pictures').getPublickUrl(`${title}.${imageExt}`)
-
Далее сгенерируем картинку: const image = document.createElement('img')
-
Задаем ссылку на изображение в базе: image.src = publicURL
-
Потом ширину и высоту: image.width = 200 и image.height = 200
-
В конце прикрепляем получившуюся иллюстрацию к блоку imageBlock таким образом: imageBlock.appendChild(image)
Эту функцию мы будем запускать каждый раз при рендеринге элемента со статьей, так что сразу добавим ее в тело onMount.
![]()
Второй способ добавления изображений немного проще. Сама функция работает аналогично: берем те же данные, ищем картинку и ссылку на нее, но вместо того, чтобы генерировать картинку с нуля, мы создаем переменную url и добавляем ее в уже подготовленный элемент img в разметке.
<img width=100 height=50 src={url} alt />
![]()
Значение url мы будем менять на publicURL внутри onMount. Такой метод я использовал в компоненте Post.svelte, чтобы загружать миниатюрные изображения в списке постов.
![]()
Вместо заключения
На стадии рефакторинга мы немного изменим алгоритмы и в целом упростим процедуру привязки картинок к статьям. Уже сейчас мы имеем рабочий код, справляющийся со своей задачей и работающий вполне предсказуемо.
Как всегда, если будут вопросы, обязательно пишите в комментариях.
Продолжение: Создаем блог на Svelte. Часть 8: Лайки
Комментарии