Подключение MinIO
Внимание
Данная статья документации написана нейросетью. Возможны некоторые расхождения и неточность информации!
Руководство по подключению к MinIO (S3-совместимое хранилище) в IO7 фреймворке.
Требования
Для работы с MinIO необходим пакет aws/aws-sdk-php:
composer require aws/aws-sdk-php
MinioManager
Пространство имён: IO\Storage
Менеджер для работы с MinIO S3-хранилищем. Реализован как синглтон.
Инициализация
init()
public static function init(array $config): self
Инициализировать или получить существующий экземпляр.
| Параметр | Тип | Значение по умолчанию | Обязателен | Описание |
|---|---|---|---|---|
$config | array | — | Да | Конфигурация подключения |
Параметры конфигурации:
| Ключ | Значение по умолчанию | Обязателен | Описание |
|---|---|---|---|
endpoint | — | Да | URL MinIO сервера |
key | — | Да | Access Key |
secret | — | Да | Secret Key |
bucket | — | Да | Имя бакета |
region | 'us-east-1' | Нет | Регион |
cdn_url | null | Нет | CDN URL для файлов |
use IO\Storage\MinioManager;
MinioManager::init([
'endpoint' => 'https://minio.example.com',
'key' => 'AKIAIOSFODNN7EXAMPLE',
'secret' => 'wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY',
'bucket' => 'my-bucket',
'region' => 'us-east-1',
'cdn_url' => 'https://cdn.example.com/',
]);
getInstance()
public static function getInstance(): self
Получить синглтон-экземпляр. Выбрасывает \Exception если не инициализирован.
$minio = MinioManager::getInstance();
Методы
upload()
public function upload(
string $localPath,
string $remotePath,
string $acl = 'public-read'
): array
Загрузить файл с локального диска.
| Параметр | Тип | Значение по умолчанию | Обязателен | Описание |
|---|---|---|---|---|
$localPath | string | — | Да | Локальный путь к файлу |
$remotePath | string | — | Да | Удалённый путь в бакете |
$acl | string | 'public-read' | Нет | ACL права |
Возвращает:
// Успех:
['success' => true, 'url' => '...', 'cdn_url' => '...']
// Ошибка:
['success' => false, 'error' => '...']
$result = MinioManager::getInstance()->upload(
'/tmp/photo.jpg',
'images/2024/photo.jpg'
);
if ($result['success']) {
echo "Файл загружен: {$result['cdn_url']}";
}
uploadContent()
public function uploadContent(
string $content,
string $remotePath,
string $contentType = 'application/octet-stream'
): array
Загрузить контент напрямую (без файла на диске).
| Параметр | Тип | Значение по умолчанию | Обязателен | Описание |
|---|---|---|---|---|
$content | string | — | Да | Контент для загрузки |
$remotePath | string | — | Да | Удалённый путь |
$contentType | string | 'application/octet-stream' | Нет | MIME тип |
$json = json_encode(['config' => 'value']);
$result = MinioManager::getInstance()->uploadContent(
$json,
'configs/app.json',
'application/json'
);
download()
public function download(string $remotePath): array
Скачать файл из бакета.
Возвращает:
// Успех:
['success' => true, 'content' => '...', 'content_type' => '...']
// Ошибка:
['success' => false, 'error' => '...']
$result = MinioManager::getInstance()->download('docs/report.pdf');
if ($result['success']) {
file_put_contents('/tmp/report.pdf', $result['content']);
}
delete()
public function delete(string $remotePath): array
Удалить файл из бакета.
$result = MinioManager::getInstance()->delete('images/old_photo.jpg');
getTemporaryUrl()
public function getTemporaryUrl(
string $remotePath,
int $expires = 3600
): ?string
Получить временную URL для доступа к файлу.
| Параметр | Тип | Значение по умолчанию | Обязателен | Описание |
|---|---|---|---|---|
$remotePath | string | — | Да | Путь к файлу |
$expires | int | 3600 | Нет | Время жизни URL в секундах (1 час) |
$url = MinioManager::getInstance()->getTemporaryUrl('docs/private.pdf', 300);
// 'https://minio.example.com/my-bucket/docs/private.pdf?X-Amz-Algorithm=...'
if ($url) {
header("Location: $url");
}
getMetadata()
public function getMetadata(string $remotePath): array
Получить метаданные файла.
Возвращает:
// Успех:
[
'success' => true,
'size' => 123456,
'content_type' => 'image/jpeg',
'last_modified' => '2024-01-15 10:30:00',
'etag' => '"abc123..."',
]
// Ошибка:
['success' => false, 'error' => '...']
$meta = MinioManager::getInstance()->getMetadata('images/photo.jpg');
echo "Размер: {$meta['size']} байт\n";
echo "Тип: {$meta['content_type']}\n";
listFiles()
public function listFiles(
string $prefix = '',
int $maxKeys = 1000
): array
Список файлов в бакете.
| Параметр | Тип | Значение по умолчанию | Обязателен | Описание |
|---|---|---|---|---|
$prefix | string | '' | Нет | Префикс для фильтрации (все файлы) |
$maxKeys | int | 1000 | Нет | Максимальное количество файлов |
Возвращает:
// Успех:
[
'success' => true,
'files' => [
['key' => 'images/1.jpg', 'size' => 1234, 'last_modified' => '...', 'etag' => '...'],
// ...
],
'count' => 5,
]
// Ошибка:
['success' => false, 'error' => '...']
$result = MinioManager::getInstance()->listFiles('images/', 50);
foreach ($result['files'] as $file) {
echo "{$file['key']} ({$file['size']} байт)\n";
}
Примеры
Базовая загрузка
use IO\Storage\MinioManager;
MinioManager::init([
'endpoint' => 'https://minio.example.com',
'key' => 'YOUR_ACCESS_KEY',
'secret' => 'YOUR_SECRET_KEY',
'bucket' => 'uploads',
]);
// Загрузка фото
$result = MinioManager::getInstance()->upload(
$_FILES['photo']['tmp_name'],
'photos/' . time() . '_' . $_FILES['photo']['name']
);
if ($result['success']) {
echo "Фото загружено: {$result['cdn_url']}";
} else {
echo "Ошибка: {$result['error']}";
}
Загрузка из API
$content = file_get_contents('php://input');
$result = MinioManager::getInstance()->uploadContent(
$content,
'api/data_' . date('Y-m-d') . '.json',
'application/json'
);
Генерация ссылки для скачивания
// Приватный файл — временная ссылка на 5 минут
$url = MinioManager::getInstance()->getTemporaryUrl(
'documents/contract.pdf',
300
);
header("Location: $url");
exit;
Управление файлами
$minio = MinioManager::getInstance();
// Список файлов
$files = $minio->listFiles('uploads/2024/');
// Метаданные
foreach ($files['files'] as $file) {
$meta = $minio->getMetadata($file['key']);
echo "{$file['key']}: {$meta['size']} байт, {$meta['content_type']}\n";
}
// Удаление старых файлов
$minio->delete('uploads/2023/old_file.jpg');
Загрузка с ACL
// Приватный файл
$result = MinioManager::getInstance()->upload(
'/tmp/private.pdf',
'docs/private.pdf',
'private'
);
// Публичный файл
$result = MinioManager::getInstance()->upload(
'/tmp/public.jpg',
'images/public.jpg',
'public-read'
);
Рекомендации
- Используйте
cdn_urlдля раздачи статических файлов через CDN - Настройте ACL —
privateдля приватных данных,public-readдля публичных - Генерируйте уникальные имена файлов (timestamp + hash)
- Используйте
getTemporaryUrl()для приватных файлов - Храните структуру — organized by date/type
- Проверяйте
successперед использованием результата
FAQ
Как настроить MinIO?
# Docker
docker run -p 9000:9000 -p 9001:9001 \
-e MINIO_ROOT_USER=admin \
-e MINIO_ROOT_PASSWORD=password \
minio/minio server /data --console-address ":9001"
Как загрузить файл больше 5GB?
MinIO поддерживает multipart upload через AWS SDK. Используйте uploadContent() для больших файлов или разбейте на части.
Как проверить, что файл загружен?
$meta = $minio->getMetadata($remotePath);
if ($meta['success']) {
echo "Файл существует, размер: {$meta['size']}\n";
}
Как скачать файл в браузере?
$result = $minio->download('files/report.pdf');
if ($result['success']) {
header('Content-Type: ' . $result['content_type']);
header('Content-Disposition: attachment; filename="report.pdf"');
echo $result['content'];
}
Как работает CDN?
Если задан cdn_url в конфигурации, метод upload() возвращает cdn_url вместо прямой URL MinIO. Используйте cdn_url для раздачи файлов конечным пользователям.