Гид по технологиям

Загрузка и обслуживание изображений в Supabase Storage для Next.js

7 min read Разработка Обновлено 06 Jan 2026
Supabase: загрузка изображений в Next.js
Supabase: загрузка изображений в Next.js

Три пронумерованных складских контейнера с синими роллетными дверями

О чём статья

Это пошаговое руководство объясняет, как настроить проект Supabase и bucket для хранения изображений, как инициализировать supabase-js в Next.js, как сделать форму загрузки и как безопасно выдавать загруженные файлы в приложении. Дополнительно указаны альтернативы, критерии приёмки, чеклисты ролей, советы по безопасности и тесты.

Создание проекта Supabase

Если у вас ещё нет приложения Next.js, начните с официального руководства Next.js, чтобы создать его.

Дальше создайте проект Supabase:

  1. Зайдите на сайт Supabase и зарегистрируйтесь или войдите в аккаунт.
  2. В панели Supabase нажмите “Create a new project”.
  3. Укажите имя проекта и нажмите “Create project”. После создания вы попадёте в панель управления проекта.

После создания проекта нужно добавить storage bucket.

Создание storage bucket в Supabase

Bucket — это место для файлов: изображений, видео и других статических активов. Его можно создать через Dashboard или через API/клиент.

Через Dashboard:

  1. Откройте страницу Storage в Dashboard.
  2. Нажмите “New Bucket” и задайте имя, например images.
  3. Нажмите “Create Bucket”.

Далее настроим клиент Supabase в приложении.

Настройка Supabase клиента

Установите клиентскую библиотеку supabase-js:

npm install @supabase/supabase-js  

В корне приложения создайте папку lib (или используйте src/lib). В ней создайте файл supabase.js и инициализируйте клиент:

import { createClient } from '@supabase/supabase-js'

export const supabase = createClient('', '')

Рекомендуется хранить значения в переменных окружения. В .env добавьте:

SUPABASE_PROJECT_URL="your_project_url"
SUPABASE_PROJECT_ANON_KEY="your_project_anon_key"

И в supabase.js используйте переменные окружения:

export const supabase = createClient(
  process.env.SUPABASE_PROJECT_URL,
  process.env.SUPABASE_ANON_KEY
);

Теперь создадим страницу с формой для приёма файлов.

Создание формы для загрузки изображений

В Next.js (app router) создайте папку upload и файл page.js — это сделает маршрут /upload. Для Next.js 12 используйте pages/upload.js.

Пример компонента с формой (React client component):

"use client";
import { useState } from "react";

export default function Page() {
  const [file, setfile] = useState([]);

  const handleSubmit = async (e) => {
    e.preventDefault();
    // upload image
  };

  const handleFileSelected = (e) => {
    setfile(e.target.files[0]);
  };

  return (
    
); }

Когда вы выберете файл и отправите форму, вызовется handleSubmit — именно в нём будет логика загрузки.

Для больших форм с валидацией разумно рассмотреть библиотеки типа Formik или React Hook Form.

Загрузка файла в Supabase Storage

Внутри handleSubmit используйте клиент Supabase для загрузки в bucket. Примерный код:

const handleSubmit = async (e) => {
    e.preventDefault();
    const filename = `${uuidv4()}-${file.name}`;

    const { data, error } = await supabase.storage
      .from("images")
      .upload(filename, file, {
        cacheControl: "3600",
        upsert: false,
      });

    const filepath = data.path;
    // save filepath in database
  };

Здесь мы создаём уникальное имя файла с помощью UUID, чтобы избежать перезаписывания файлов с одинаковыми именами.

Установите пакет uuid:

npm install uuid

Импортируйте UUID вверху страницы:

import { v4 as uuidv4 } from "uuid";

Не забудьте импортировать supabase клиент:

import { supabase } from "@/lib/supabase";

Путь к файлу в bucket ведёт себя как файловая система: если у вас есть папка public в bucket, укажите “/public/filename”.

После успешной загрузки Supabase вернёт объект data, в котором находится путь к файлу (data.path). Сохраните этот путь в вашей базе данных (Postgres), чтобы позже связывать файл с сущностью (пользователь, пост и т.д.).

Политики доступа для загрузки

Для работы загрузки нужно добавить политику, разрешающую INSERT и SELECT к Storage (если вы используете Row Level Security и хотите разрешить доступ приложению):

  1. В Dashboard проекта откройте Storage.
  2. Выберите ваш bucket и вкладку Access.
  3. В разделе Bucket policies нажмите New policy.
  4. Выберите For full customization.
  5. Дайте имя политике, например Allow Insert and Read.
  6. Установите Allowed operations: INSERT и SELECT.
  7. Нажмите Review и затем Save.

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

Отдача (serve) загруженных изображений в приложении

Чтобы показать изображение в приложении, вам нужен публичный URL. Его можно получить двумя способами.

  1. Через supabase-js:
const filepath = "path_to_file_in_bucket"

const { data } = supabase
  .storage
  .from('images')
  .getPublicUrl(`${filepath}`)
  1. Сконструировать URL вручную, объединяя базовый URL bucket и путь к файлу:
const filepath = `${bucket_url}/${filepath}`

Далее используйте компонент Image из Next.js:

Загруженное изображение

Если вы используете приватные файлы, вместо getPublicUrl используйте .createSignedUrl для временных ссылок.

Когда такой подход не подходит

  • Когда вам требуется мгновенное финальное CDN-кеширование со сложными правилами — стоит интегрировать CDN (Cloudflare/KeyCDN) или использовать S3/GCS с CDN.
  • Если объём изображений очень большой и нужна многоуровневая обработка (трансформация изображений на лету) — рассмотрите специализированные сервисы (ImageKit, Cloudinary).
  • Для критичных по задержке задач (стриминг, live-обновления) возможно понадобятся другие архитектурные решения.

Альтернативные подходы

  • Хранить файлы в S3 (AWS) или GCS (Google Cloud Storage) и использовать тот же принцип: генерировать уникальные имена, хранить путь в базе, отдавать публичные или подписанные URL.
  • Использовать CDN с origin на Supabase или S3 для ускорения отдачи.
  • Использовать специализированные сервисы изображений для автоматических ресайзов и оптимизации.

Модель мышления и эвристики при выборе

  • Если нужно просто хранить и отдавать файлы — Supabase Storage подходит по цене и интеграции.
  • Если нужна глобальная низкая задержка и масштабируемость — используйте CDN на верхнем слое.
  • Если нужна обработка изображений (ресайз, форматы WebP/AVIF) — используйте сервис с этими возможностями или добавьте обработку на сервере/edge.

Мини‑методология внедрения (пошагово)

  1. Создать проект Supabase и bucket images.
  2. Настроить переменные окружения и инициализировать supabase-js.
  3. Сделать форму загрузки в Next.js и реализовать логику upload с уникальными именами.
  4. Сохранить путь к файлу в Postgres вместе с метаданными (owner, mime-type, created_at).
  5. Настроить политики доступа в Storage.
  6. Решить вопрос с публичностью/подписанными URL и CDN.
  7. Написать тесты и мониторинг.

Чеклист ролей при релизе

  • Разработчик:
    • Реализовал upload и сохранение пути в БД.
    • Добавил обработку ошибок и валидировал тип/размер файла.
  • DevOps:
    • Настроил переменные окружения в окружении развертывания.
    • Проверил политики доступа и резервное копирование.
  • Продукт/PM:
    • Утвердил требования к размерам и формату изображений.
    • Решил вопрос с политикой хранения и срока хранения файлов.

Критерии приёмки

  • Форма успешно загружает изображения в bucket images.
  • В базе данных сохраняется корректный путь к файлу.
  • Изображение отображается в Next.js через public URL или signed URL.
  • Нельзя загрузить файлы превышающие ограничение по размеру (если задано).
  • Политики доступа не позволяют неавторизованному доступу к приватным файлам.

Тестовые сценарии и приёмочные тесты

  • Попытка загрузить допустимый файл — загрузка успешна и путь сохранён.
  • Попытка загрузить файл с тем же именем — файл сохраняется под уникальным именем.
  • Попытка загрузить файл запрещённого типа — загрузка отклоняется.
  • Получение signed URL для приватного файла — URL работает в течение заданного времени.

Советы по безопасности и приватности

  • Не храните секреты (anon key, service role key) в клиентском коде. anon key допустим для клиентского доступа, service role key только на сервере.
  • Для приватных файлов используйте подписанные URL с ограниченным сроком жизни.
  • Ограничьте типы и размеры файлов на стороне сервера/фронтенда.
  • Логируйте ошибки загрузки и доступ к файлам для аудита.
  • Учтите требования GDPR: храните только необходимые метаданные и давайте пользователям возможность удалять свои файлы.

Миграция и совместимость

  • При переносе данных с файловой системы на Supabase/облако — экспортируйте файлы и сохраните новые пути в базе.
  • Если вы используете Next.js Image Optimization, добавьте домен Supabase/ CDN в next.config.js domains.

Шпаргалка (cheat sheet)

  • Уникальное имя: ${uuidv4()}-${file.name}
  • Загрузка: supabase.storage.from(‘images’).upload(path, file)
  • Публичный URL: supabase.storage.from(‘images’).getPublicUrl(path)
  • Подписанный URL (private): supabase.storage.from(‘images’).createSignedUrl(path, expiresInSeconds)

Факто‑бокс с ключевыми моментами

  • Хранение в базе BLOB: дорого и не масштабируется.
  • Supabase Storage: удобен для файлов и интеграции с Postgres.
  • UUID: помогает избежать конфликтов имён.
  • Signed URL: безопасный способ отдачи приватных файлов.

Пример объявления релиза (короткая версия)

В проект добавлена возможность загружать и хранить изображения в Supabase Storage. Реализована форма загрузки, сохранение пути в Postgres и отдача изображений через публичные или подписанные URL.

Социальный предпросмотр

OG title: “Supabase: загрузка изображений в Next.js” OG description: “Пошаговое руководство по загрузке и выдаче изображений через Supabase Storage и supabase-js для Next.js.”

Заключение

Хранение изображений в Supabase Storage — простой и масштабируемый способ для большинства веб-приложений. Это лучше, чем хранить BLOB в базе данных: меньше затрат, проще интеграция с CDN и безопасные ссылки. Планируйте обработку изображений и политику доступа заранее, тестируйте сценарии загрузки и доступа, и вы получите надёжную систему управления медиа.

Поделиться: X/Twitter Facebook LinkedIn Telegram
Автор
Редакция

Похожие материалы

Как хранить данные PS5 в облаке и освобождать место
Игры

Как хранить данные PS5 в облаке и освобождать место

Вход через соцсети в WordPress с Super Socializer
WordPress

Вход через соцсети в WordPress с Super Socializer

Как Firefox удаляет параметры запроса и защищает приватность
Конфиденциальность

Как Firefox удаляет параметры запроса и защищает приватность

Как подключить Ring к Google Home
Умный дом

Как подключить Ring к Google Home

Дни отдыха после тренировок — план для восстановления
Фитнес

Дни отдыха после тренировок — план для восстановления

Microsoft Designer — быстрый дизайн для соцсетей
Дизайн

Microsoft Designer — быстрый дизайн для соцсетей