Настройка хранилища файлов (S3/MinIO) для веб-приложения

Наша компания занимается разработкой, поддержкой и обслуживанием сайтов любой сложности. От простых одностраничных сайтов до масштабных кластерных систем построенных на микро сервисах. Опыт разработчиков подтвержден сертификатами от вендоров.

Разработка и обслуживание любых видов сайтов:

Информационные сайты или веб-приложения
Сайты визитки, landing page, корпоративные сайты, онлайн каталоги, квиз, промо-сайты, блоги, новостные ресурсы, информационные порталы, форумы, агрегаторы
Сайты или веб-приложения электронной коммерции
Интернет-магазины, B2B-порталы, маркетплейсы, онлайн-обменники, кэшбэк-сайты, биржи, дропшиппинг-платформы, парсеры товаров
Веб-приложения для управления бизнес-процессами
CRM-системы, ERP-системы, корпоративные порталы, системы управления производством, парсеры информации
Сайты или веб-приложения электронных услуг
Доски объявлений, онлайн-школы, онлайн-кинотеатры, конструкторы сайтов, порталы предоставления электронных услуг, видеохостинги, тематические порталы

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

Предлагаемые услуги
Показано 1 из 1 услугВсе 2065 услуг
Настройка хранилища файлов (S3/MinIO) для веб-приложения
Средняя
~2-3 рабочих дня
Часто задаваемые вопросы

Наши компетенции:

Этапы разработки

Последние работы

  • image_website-b2b-advance_0.png
    Разработка сайта компании B2B ADVANCE
    1262
  • image_web-applications_feedme_466_0.webp
    Разработка веб-приложения для компании FEEDME
    1171
  • image_websites_belfingroup_462_0.webp
    Разработка веб-сайта для компании БЕЛФИНГРУПП
    874
  • image_ecommerce_furnoro_435_0.webp
    Разработка интернет магазина для компании FURNORO
    1094
  • image_crm_enviok_479_0.webp
    Разработка веб-приложения для компании Enviok
    831
  • image_bitrix-bitrix-24-1c_fixper_448_0.png
    Разработка веб-сайта для компании ФИКСПЕР
    851

Настройка файлового хранилища S3 и MinIO

S3-совместимые хранилища хранят загружаемые файлы (фото, документы, видео) отдельно от сервера приложения. MinIO — self-hosted альтернатива AWS S3 с идентичным API.

AWS S3: базовая настройка

# Terraform
resource "aws_s3_bucket" "uploads" {
  bucket = "myapp-uploads-production"
}

resource "aws_s3_bucket_public_access_block" "uploads" {
  bucket                  = aws_s3_bucket.uploads.id
  block_public_acls       = true
  block_public_policy     = true
  ignore_public_acls      = true
  restrict_public_buckets = true
}

resource "aws_s3_bucket_versioning" "uploads" {
  bucket = aws_s3_bucket.uploads.id
  versioning_configuration { status = "Enabled" }
}

resource "aws_s3_bucket_server_side_encryption_configuration" "uploads" {
  bucket = aws_s3_bucket.uploads.id
  rule {
    apply_server_side_encryption_by_default {
      sse_algorithm = "AES256"
    }
  }
}

Presigned URLs для безопасной загрузки

Клиент загружает файл напрямую в S3, минуя сервер. Сервер генерирует подписанный URL с ограниченным временем жизни.

// Laravel + aws-sdk-php
use Aws\S3\S3Client;
use Aws\S3\PostObjectV4;

class FileUploadController extends Controller
{
    public function presign(Request $request): JsonResponse
    {
        $request->validate([
            'filename' => 'required|string|max:255',
            'content_type' => 'required|string',
        ]);

        $key = 'uploads/' . auth()->id() . '/' . Str::uuid() . '/' .
               pathinfo($request->filename, PATHINFO_BASENAME);

        $s3 = app('aws')->createClient('s3');

        $command = $s3->getCommand('PutObject', [
            'Bucket'       => config('filesystems.disks.s3.bucket'),
            'Key'          => $key,
            'ContentType'  => $request->content_type,
            'ACL'          => 'private',
        ]);

        $presigned = $s3->createPresignedRequest($command, '+15 minutes');

        return response()->json([
            'upload_url' => (string) $presigned->getUri(),
            'key'        => $key,
        ]);
    }
}
// React: загрузка через presigned URL
async function uploadFile(file: File): Promise<string> {
  const { upload_url, key } = await api.post('/api/presign', {
    filename: file.name,
    content_type: file.type,
  });

  await fetch(upload_url, {
    method: 'PUT',
    body: file,
    headers: { 'Content-Type': file.type },
  });

  return key;
}

MinIO: self-hosted развёртывание

# docker-compose.yml
services:
  minio:
    image: minio/minio:latest
    command: server /data --console-address ":9001"
    environment:
      MINIO_ROOT_USER: minioadmin
      MINIO_ROOT_PASSWORD: ${MINIO_PASSWORD}
    volumes:
      - minio_data:/data
    ports:
      - "9000:9000"   # S3 API
      - "9001:9001"   # Web console
    healthcheck:
      test: ["CMD", "mc", "ready", "local"]
      interval: 10s

volumes:
  minio_data:

MinIO имеет идентичный AWS S3 API — достаточно изменить endpoint в конфигурации:

AWS_ACCESS_KEY_ID=minioadmin
AWS_SECRET_ACCESS_KEY=miniopassword
AWS_DEFAULT_REGION=us-east-1
AWS_BUCKET=uploads
AWS_URL=http://minio:9000
AWS_ENDPOINT=http://minio:9000
AWS_USE_PATH_STYLE_ENDPOINT=true

Интеграция с Laravel Filesystem

// config/filesystems.php
's3' => [
    'driver'                  => 's3',
    'key'                     => env('AWS_ACCESS_KEY_ID'),
    'secret'                  => env('AWS_SECRET_ACCESS_KEY'),
    'region'                  => env('AWS_DEFAULT_REGION'),
    'bucket'                  => env('AWS_BUCKET'),
    'url'                     => env('AWS_URL'),
    'endpoint'                => env('AWS_ENDPOINT'),
    'use_path_style_endpoint' => env('AWS_USE_PATH_STYLE_ENDPOINT', false),
    'throw'                   => true,
],

// Использование
$path = Storage::disk('s3')->putFile('uploads', $request->file('photo'));
$url  = Storage::disk('s3')->temporaryUrl($path, now()->addMinutes(60));

Жизненный цикл и очистка

resource "aws_s3_bucket_lifecycle_configuration" "uploads" {
  bucket = aws_s3_bucket.uploads.id

  rule {
    id     = "move-to-glacier"
    status = "Enabled"

    transition {
      days          = 90
      storage_class = "GLACIER"
    }

    expiration {
      days = 365
    }

    filter {
      prefix = "temp/"
    }
  }
}

Срок реализации

AWS S3 с presigned URLs для Laravel/Node.js: 1–2 дня. MinIO self-hosted с Docker: 1 день. Оба варианта с lifecycle rules и мониторингом: 3 дня.