Перейти к основному содержимому

Приложение с S3, PostgreSQL и ASP.NET Core Web API

Разработчику Архитектору

Приложение с S3, PostgreSQL и ASP.NET Core Web API

Для первого знакомства с API начните с Первая программа на ASP.NET Core. Для запросов к PostgreSQL через EF и LINQ держите под рукой полный LINQ API-справочник.

В этой статье вы собираете архитектурно приближённый к production учебный сервис. Основная ценность материала в том, что здесь соединяются сразу несколько практик — HTTP API, объектное хранилище, реляционная база и контейнерное окружение.

Что получить на выходе

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


Облачные технологии и микросервисная архитектура

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

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

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

Паттерны проектирования играют ключевую роль в создании надежных и поддерживаемых систем. Паттерн — это проверенное временем решение типовой проблемы проектирования. Использование паттернов позволяет разработчикам не изобретать велосипед заново, а применять готовые архитектурные решения, которые уже доказали свою эффективность. В данном проекте мы применяем паттерн разделения ответственности между слоями приложения:

  • слой представления (контроллеры),
  • слой логики (сервисы);
  • слой доступа к данным (репозитории).

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

В этом разделе мы рассмотрим создание сервиса управления медиафайлами. Этот сервис обеспечивает загрузку файлов в объектное хранилище, хранение метаданных о файлах в реляционной базе данных и предоставляет REST API для взаимодействия с данными. Сервис принимает файл от клиента, сохраняет его содержимое в объектном хранилище, записывает информацию о файле (имя, размер, тип, дату создания) в базу данных и возвращает клиенту подтверждение успешной загрузки. Такой подход позволяет разделить хранение больших бинарных данных (сам файл) и структурированной информации (метаданные), что повышает производительность и масштабируемость системы. Объектное хранилище отлично подходит для хранения файлов, так как оно способно работать с огромными объемами неструктурированных данных, в то время как реляционная база данных эффективно управляет связями и поиском по метаданным.


Объектное хранилище S3 и библиотеки Amazon S3

Объектное хранилище S3 (Simple Storage Service) — это служба хранения объектов, разработанная компанией Amazon Web Services. Служба позволяет хранить и получать любые объемы данных практически неограниченное количество времени.

Данные в S3 хранятся в виде объектов, каждый из которых состоит из:

  • самого файла,
  • уникального идентификатора (ключа);
  • набора метаданных.

Объекты группируются в бакеты (buckets), которые представляют собой контейнеры верхнего уровня. Бакет имеет глобально уникальное имя и служит для логической организации данных.

Библиотека Amazon S3 SDK — это набор классов и методов, предоставляемый Amazon для работы с облачным хранилищем S3 из приложений, написанных на различных языках программирования. Библиотека абстрагирует сложные детали сетевого взаимодействия, аутентификации и шифрования, предоставляя простой интерфейс для выполнения операций с объектами — загрузка, скачивание, удаление, получение списка объектов.

Подключение библиотеки к проекту осуществляется через систему управления пакетами. В среде .NET это делается через NuGet Package Manager или командную строку. Установка пакета добавляет необходимые DLL-файлы в проект, что позволяет использовать классы Amazon.S3 и связанные с ними методы.

Для локальной разработки и тестирования использование реального облачного хранилища Amazon S3 может быть неудобным по нескольким причинам:

  1. Требуется регистрация аккаунта и настройка прав доступа.
  2. Работа с реальным облаком связана с затратами, даже если тарифный план включает бесплатный уровень.
  3. Скорость работы с удаленным сервером зависит от качества интернет-соединения. Для этих целей лучше использовать эмулятор MinIO.

MinIO — это высокопроизводительное объектное хранилище, совместимое с API Amazon S3. Оно работает локально, не требует подключения к интернету и полностью бесплатное. Эмулятор имитирует поведение реального S3, позволяя разработчикам тестировать код в условиях, максимально приближенных к продакшену, но без затрат и ограничений внешнего сервиса.

MinIO отличается от Amazon S3 тем, что это самостоятельная система хранения, развертываемая на собственном оборудовании или в виртуальной машине, тогда как Amazon S3 — это управляемый сервис в облаке AWS. MinIO предоставляет те же основные операции с объектами, поддерживает ту же структуру API, что делает миграцию с MinIO на Amazon S3 или наоборот минимально трудоемкой. Установка реальной S3 в производственной среде обычно означает аренду соответствующего сервиса у провайдера AWS. Это не требует установки программного обеспечения на свои серверы, так как вся инфраструктура находится под управлением Amazon. Пользователь получает доступ к сервису через API, используя свои учетные данные (Access Key и Secret Key), полученные после регистрации.


Сервис управления медиафайлами

Сервис управления медиафайлами — это специализированное программное обеспечение, предназначенное для обработки, хранения и предоставления доступа к мультимедийным контентам. Такой сервис обеспечивает загрузку файлов в объектное хранилище, где они сохраняются как объекты с уникальными именами. Одновременно с этим сервис хранит метаданные о каждом файле в реляционной базе данных.

Метаданные включают информацию об имени файла, размере, типе контента (MIME-тип), дате создания и другие атрибуты.

Предоставление REST API позволяет другим приложениям взаимодействовать с этим сервисом, отправляя запросы на загрузку, получение списка файлов, удаление файлов и другие операции.

Хранение самих файлов в базе данных нецелесообразно, так как базы данных оптимизированы для работы со структурированными данными, а не с большими бинарными блоками. Разделение хранения файла и метаданных позволяет использовать преимущества обоих типов хранилищ: высокая скорость поиска и фильтрации по метаданным в реляционной базе и надежное хранение больших объемов данных в объектном хранилище. Сервис также обеспечивает безопасность данных, контролируя права доступа к файлам, и может предоставлять функции кэширования, сжатия и конвертации изображений или видео.


Стек технологий проекта

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

  • ASP.NET Core Web API — это фреймворк для создания RESTful API и веб-сервисов. Версия .NET 10 предлагает последние улучшения в производительности, безопасности и поддержке новых стандартов. Фреймворк работает кроссплатформенно, поддерживает асинхронное программирование и предоставляет встроенные механизмы для встраивания документации и тестирования.
  • MinIO — это эмулятор Amazon S3, используемый для локального развития. Он запускается в контейнере Docker, что упрощает развертывание и изоляцию среды. MinIO обеспечивает полную совместимость с API S3, позволяя использовать стандартные библиотеки для работы с облачным хранилищем.
  • PostgreSQL — это мощная реляционная система управления базами данных с открытым исходным кодом. Она поддерживает сложные запросы, транзакции, индексы и расширения. PostgreSQL идеально подходит для хранения метаданных благодаря своей надежности и способности обрабатывать большие объемы структурированных данных.
  • Entity Framework Core — это объектно-реляционный маппер (ORM), который позволяет работать с базой данных как с коллекциями объектов на языке C#. Подход Code First означает, что модель данных определяется в коде, а затем на основе этой модели автоматически создаются таблицы базы данных. Это ускоряет процесс разработки и упрощает изменение структуры данных.
  • Библиотека Minio.Client — это нативная библиотека для работы с MinIO, аналогичная AWS SDK для S3. Она предоставляет методы для выполнения всех основных операций с объектами — создание бакета, загрузка файла, получение ссылки на скачивание, удаление объекта. Библиотека оптимизирована для высокой производительности и безопасного взаимодействия с хранилищем.
  • Swagger / OpenAPI (Swashbuckle.AspNetCore) — это инструмент для автоматической генерации интерактивной документации API. Swagger UI позволяет разработчикам и пользователям видеть все доступные эндпоинты, параметры запросов и примеры ответов прямо в браузере, что упрощает интеграцию с другими системами.
  • Docker — это платформа для контейнеризации приложений. Контейнер — это легковесная, переносимая единица программного обеспечения, которая содержит всё необходимое для запуска приложения — код, среду выполнения, библиотеки и настройки. Использование Docker позволяет легко развернуть MinIO и другие зависимости в изолированной среде, исключая конфликты версий и проблем с окружением.

Почему этот стек хорошо подходит для учебного микросервиса

  • Разделение ответственности: бинарные данные и метаданные хранятся в оптимальных для них системах.
  • Масштабируемость: можно отдельно масштабировать API, БД и хранилище.
  • Наблюдаемость: проблемы проще диагностировать по слоям (API, БД, S3).
  • Портируемость: Docker окружение воспроизводится у всей команды.
  • Близость к production: такой же паттерн часто используется в реальных B2B- и SaaS-системах.

Установка и настройка среды разработки

Установка Visual Studio и .NET 10

Первым шагом является установка интегрированной среды разработки Visual Studio.

Рекомендуется использовать последнюю версию Visual Studio 2022 Community или Professional.

При установке необходимо выбрать рабочую нагрузку "Разработка веб-приложений" (.NET Desktop Разработка не требуется для этого проекта).

Проверка SDK:

dotnet --version

Установка пакетов NuGet

После создания проекта необходимо добавить необходимые пакеты. В среде Visual Studio это делается через менеджер пакетов.

Откройте окно Управление пакетами NuGet (меню Проект -> Управление пакетами NuGet) и установите следующие пакеты:

ПакетНазначение
Microsoft.EntityFrameworkCore.ПроектированиеИнструментарий для создания миграций БД
Microsoft.EntityFrameworkCore.ToolsКоманды Package Manager Console (Add-Migration, Update-Database)
Npgsql.EntityFrameworkCore.PostgreSQLProvider для подключения к PostgreSQL
MinioКлиент для работы с MinIO (замена AWS SDK)
Swashbuckle.AspNetCoreГенерация документации Swagger UI

Эти пакеты обеспечивают функциональность работы с базой данных, подключение к PostgreSQL, взаимодействие с объектным хранилищем и генерацию документации API.


Установка и запуск Docker Desktop

Необходимо установить Docker Desktop для вашей операционной системы. После установки запустите приложение и дождитесь полной инициализации Docker Engine.

Проверка Docker:

docker --version

Запуск MinIO в контейнере (одна строка в терминале проекта):

docker run -p 9000:9000 -p 9001:9001 --name s3-local -e "MINIO_ROOT_USER=minioadmin" -e "MINIO_ROOT_PASSWORD=minioadmin" -v minio-data:/data minio/minio server /data --console-address ":9001"

Эта команда создает и запускает контейнер с именем s3-local.

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

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

Имя пользователя по умолчанию — minioadmin, пароль — minioadmin.

Данные будут сохраняться в томе minio-data, что гарантирует их сохранение при перезапуске контейнера.


Установка PostgreSQL и pgAdmin

Необходимо установить СУБД PostgreSQL. Скачайте установщик с официального сайта PostgreSQL и выполните установку, приняв настройки по умолчанию или указав свой пароль суперпользователя.

Рекомендуется также установить pgAdmin — графический интерфейс для управления базами данных.

Запустите pgAdmin, создайте новое соединение с сервером PostgreSQL, используя имя хоста localhost, порт 5432, пользователя postgres и указанный вами пароль.

Внутри pgAdmin создайте новую базу данных с именем s3_media_db.

Также убедитесь, что пользователь postgres имеет соответствующие права на создание таблиц и выполнение операций с этой базой. Пароль пользователя можно изменить в свойствах соединения или через SQL-запрос, если требуется более сложная конфигурация безопасности.


Создание бакета в MinIO

Откройте браузер и перейдите по адресу http://localhost:9001.

Введите имя пользователя minioadmin и пароль minioadmin.

После входа в систему нажмите кнопку "Create Bucket". Введите имя нового бакета s3-media-manager-files.

Бакет — это контейнер верхнего уровня в объектном хранилище, аналогичный корневой директории в файловой системе. Все файлы, загружаемые в систему, будут находиться внутри этого бакета. Бакет должен иметь уникальное имя в пределах пространства имен конкретного экземпляра MinIO.

После создания бакета он появится в списке доступных контейнеров.


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

Создание проекта ASP.NET Core Web API

Откройте Visual Studio и выберите "Создание нового проекта".

Найдите шаблон "ASP.NET Core Web API". Выберите версию .NET 10.

Введите имя проекта S3MediaManager. Укажите путь к папке, созданной ранее.

Нажмите "Создать". Visual Studio создаст структуру проекта с базовыми файлами и конфигурацией.


Файл Program.cs

Файл Program.cs является точкой входа в приложение и местом регистрации всех сервисов и компонентов.

Код ITЗагрузка примера кода…


Разбор кода Program.cs

  • WebApplication.CreateBuilder(args) — статический метод, создающий экземпляр конструктора приложения. Он инициализирует сборку зависимостей, конфигурацию и среду выполнения. Переменная builder содержит все настройки, которые будут использованы при запуске приложения.
  • builder.Services — коллекция сервисов, которые регистрируются в контейнере внедрения зависимостей (Dependency Injection Container). DI позволяет создавать объекты и передавать их в нужные места без жесткого связывания кода.
  • AddDbContext<ApplicationDbContext> — метод расширения для регистрации контекста базы данных Entity Framework. Он указывает, какой класс наследуется от DbContext будет использоваться для работы с БД. Параметр options позволяет настроить подключение.
  • UseNpgsql(...) — метод, указывающий использовать драйвер Npgsql для подключения к PostgreSQL. Строка подключения берется из конфигурации.
  • Configure<S3Settings> — метод для привязки секции конфигурации к классу S3Settings. Это позволяет читать настройки из файла appsettings.json и использовать их в коде как strongly-typed объект.
  • GetSection("S3") — метод получения секции конфигурации с именем "S3". Эта секция содержит все параметры, связанные с объектным хранилищем.
  • AddSingleton<IMinioClient> — регистрация сервиса типа IMinioClient как одиночного экземпляра (Singleton). Это означает, что один и тот же объект клиента MinIO будет использоваться во всем жизненном цикле приложения, что экономит ресурсы и улучшает производительность.
  • sp.GetRequiredService<IConfiguration>() — получение сервиса конфигурации из контейнера зависимостей. sp — это поставщик сервисов (ServiceProvider), который предоставляет доступ к зарегистрированным сервисам.
  • MinioClient() — конструктор класса клиента MinIO. Методы .WithEndpoint(), .WithCredentials() и .Build() позволяют настроить адрес сервера, ключи доступа и создать финальный объект клиента.
  • AddControllers() — регистрация контроллеров MVC. Это позволяет системе автоматически обнаруживать и маршрутизировать запросы к классам, помеченным атрибутом [ApiController].
  • AddEndpointsApiExplorer() и AddSwaggerGen() — методы для включения поддержки Swagger. Первый метод добавляет метаданные API, второй генерирует документацию.
  • app.UseSwagger() и app.UseSwaggerUI() — middleware, включающие генерацию и отображение документации Swagger в браузере. Они работают только в режиме разработки (IsDevelopment).
  • UseAuthorization() — middleware, проверяющая права доступа пользователей к защищенным ресурсам.
  • MapControllers() — метод, который настраивает маршрутизацию для контроллеров. Он сопоставляет URL-адреса с методами контроллеров.
  • Run() — запускает приложение и начинает слушать входящие HTTP-запросы.
  • Класс S3Settings — модель для хранения настроек подключения к S3. Используется для сильной типизации конфигурации. Поля содержат адрес, регион, имя бакета, флаг SSL и учетные данные.
  • Класс ApplicationDbContext — контекст базы данных, наследующийся от DbContext. Определяет связь между классами C# и таблицами базы данных. Конструктор принимает настройки подключения.
  • DbSet<FileMetadata> — свойство, представляющее таблицу Files в базе данных. Entity Framework автоматически создаст эту таблицу на основе свойств класса FileMetadata.
  • Класс FileMetadata — модель данных, описывающая метаданные файла. Свойства соответствуют столбцам таблицы — уникальный идентификатор, оригинальное имя, ключ в S3, размер, тип контента и дата создания.

Файл appsettings.json

Файл appsettings.json содержит конфигурационные данные приложения.

Код ITЗагрузка примера кода…

  • Logging — секция для настройки логирования. Уровень Information выводит информационные сообщения, Warning — предупреждения.
  • AllowedHosts — список разрешенных хостов. Звездочка * означает разрешение любых хостов.
  • ConnectionStrings — раздел для строк подключения к базам данных. Ключ DefaultConnection используется в коде для получения строки подключения к PostgreSQL. Строка содержит хост, порт, имя базы данных, пользователя и пароль.
  • S3 — секция настроек для MinIO/S3. Содержит адрес эндпоинта, регион (необязательно для MinIO, но требуется по спецификации), имя бакета, флаг использования SSL и учетные данные.

Файл FilesController.cs

Контроллер отвечает за обработку HTTP-запросов, связанных с файлами.

Код ITЗагрузка примера кода…


Разбор кода FilesController.cs

  • [Route("api/[controller]")] — атрибут, определяющий базовый маршрут для всех методов контроллера. [controller] заменяется на имя контроллера (без суффикса Controller), то есть api/files.
  • [ApiController] — атрибут, включающий специальные возможности для контроллеров API: автоматическую валидацию модели, возврат ошибок 400 при неверных данных и использование статус-кодов HTTP.
  • IMinioClient, ApplicationDbContext, IConfiguration — поля класса, которые заполняются автоматически через конструктор благодаря внедрению зависимостей. _minioClient используется для работы с хранилищем, _context — для базы данных, _config — для чтения настроек.
  • UploadFile(IFormFile file) — метод обработки POST-запроса на загрузку файла. Параметр IFormFile представляет загруженный файл.
  • [HttpPost("upload")] — атрибут, указывающий, что метод обрабатывает запросы с методом POST и путем /upload. Полный путь будет api/files/upload.
  • [RequestSizeLimit(500 * 1024 * 1024)] — ограничение размера загружаемого файла. Максимум 500 МБ.
  • Path.GetExtension(file.FileName) — получение расширения файла из его имени. Например, .jpg или .pdf.
  • Guid.NewGuid() — генерация уникального идентификатора (GUID), который используется для создания уникального имени файла в хранилище, чтобы избежать коллизий.
  • MemoryStream — поток в памяти, используемый для временного хранения данных файла перед загрузкой в S3.
  • file.CopyToAsync(stream) — асинхронное копирование содержимого загруженного файла в поток.
  • BucketExistsAsync — асинхронная проверка существования бакета. Возвращает true, если бакет существует.
  • MakeBucketAsync — создание нового бакета, если он не найден.
  • PutObjectAsync — загрузка объекта (файла) в бакет. Аргументы содержат имя бакета, имя объекта, поток данных, размер и тип контента.
  • _context.Files.Add(metadata) — добавление новой записи в контекст базы данных.
  • SaveChangesAsync() — сохранение изменений в базе данных. Выполняет INSERT-запрос.
  • Ok(...) — возвращает ответ с кодом 200 OK и телом ответа в формате JSON.
  • StatusCode(500, ...) — возвращает ошибку сервера с текстом ошибки.
  • ToListAsync() — асинхронное получение всех записей из базы данных и преобразование их в список.
  • FindAsync(id) — поиск записи по первичному ключу.
  • Remove(file) — удаление записи из контекста.
  • NoContent() — возвращает ответ с кодом 204 No Content, означающий успешное удаление без тела ответа.

Применение миграций

После создания моделей необходимо применить изменения к базе данных.

Откройте окно Package Manager Console в Visual Studio (меню Вид -> Другие окна -> Package Manager Console).

В Package Manager Console:

Add-Migration InitialCreate
Update-Database

Это создаст миграцию и таблицы в PostgreSQL.


API, PostgreSQL и S3 - архитектура примера

Созданное приложение демонстрирует полноценный цикл работы с файлами в современной архитектуре. Использование API позволяет интегрировать сервис с любыми клиентами: веб-сайтами, мобильными приложениями или десктопными программами.

System обеспечивает надежное хранение файлов в объектном хранилище и быстрое управление метаданными в базе данных.

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

Применение Docker упрощает развертывание и тестирование, а использование современных библиотек и фреймворков обеспечивает безопасность и производительность. Такой подход формирует прочную основу для развития сложных информационных систем.


Куда развивать проект дальше

После базовой версии обычно добавляют:

  1. Предподписанные URL для безопасной загрузки/скачивания без проксирования файла через API.
  2. Антивирусную проверку и ограничение MIME-типа до сохранения.
  3. Версионирование API (/api/v1, /api/v2) и OpenAPI-контракты для клиентов.
  4. Фоновую обработку (preview, thumbnails, транскодирование) через очередь.
  5. Интеграционные тесты полного цикла "upload → metadata → delete".

Это логичный мост к темам Minimal API и OpenAPI, MediatR и pipeline и библиотеки для C#.


Основа по протоколу

Базовый разбор HTTP и HTTPS находится в отдельной статье — HTTP как основа веб-интеграций.


В подборках

Статья входит в тематические подборки и блок "С чего начать?" на главной. Соседние шаги того же маршрута:

Веб-разработкаДокументация и практика ASP.NET (Microsoft Learn), Python — о разделе, ASP.NET - фреймворк для веб-приложений, Веб-разработка и REST API на Python, Веб-разработка и API на C#, Социальные сети.