Работа с S3 и облачными хранилищами в JavaScript (Node.js)
S3 (Simple Storage Service) — это стандарт де-факто для объектных хранилищ в облаке. Независимо от того, используете ли вы Amazon S3, Yandex Object Storage, Mail.ru Cloud Storage или локальное решение вроде MinIO, API остаётся единым. В этой статье мы разберём, как подключаться к S3-совместимым хранилищам из Node.js с помощью официального AWS SDK v3.
Что такое S3 и зачем он нужен?
S3 позволяет хранить неограниченное количество файлов (объектов) в «корзинах» (buckets). Каждый объект имеет уникальный ключ (путь) и метаданные. Основные сценарии использования:
- Хранение пользовательских файлов (аватарки, документы)
- Бэкапы баз данных и логов
- Статические файлы для веб-приложений (изображения, CSS, JS)
- Хранение медиафайлов (видео, аудио)
Установка и настройка AWS SDK v3
Начиная с версии 3, AWS SDK стал модульным. Для работы с S3 достаточно установить один пакет:
npm install @aws-sdk/client-s3
Также вам понадобятся переменные окружения с ключами доступа. Лучше всего хранить их в .env файле:
AWS_ACCESS_KEY_ID=your_access_key
AWS_SECRET_ACCESS_KEY=your_secret_key
AWS_REGION=ru-central1
S3_ENDPOINT=https://storage.yandexcloud.net
S3_BUCKET=my-bucket
Подключение к S3-совместимому хранилищу
Создадим клиент S3 с кастомным endpoint (для Yandex Object Storage, MinIO и других):
const { S3Client } = require('@aws-sdk/client-s3');
require('dotenv').config();
const s3Client = new S3Client({
region: process.env.AWS_REGION,
endpoint: process.env.S3_ENDPOINT,
credentials: {
accessKeyId: process.env.AWS_ACCESS_KEY_ID,
secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY,
},
forcePathStyle: true, // важно для MinIO и некоторых S3-совместимых хранилищ
});
module.exports = s3Client;
Основные операции с S3
1. Загрузка файла (PutObject)
Загружаем файл из буфера или потока:
const { PutObjectCommand } = require('@aws-sdk/client-s3');
const fs = require('fs');
async function uploadFile(filePath, key) {
const fileContent = fs.readFileSync(filePath);
const command = new PutObjectCommand({
Bucket: process.env.S3_BUCKET,
Key: key,
Body: fileContent,
ContentType: 'image/png', // укажите правильный MIME-тип
});
try {
const response = await s3Client.send(command);
console.log('Файл загружен:', response.$metadata.httpStatusCode);
return `https://storage.yandexcloud.net/${process.env.S3_BUCKET}/${key}`;
} catch (err) {
console.error('Ошибка загрузки:', err);
}
}
2. Скачивание файла (GetObject)
Получаем объект и сохраняем его локально:
const { GetObjectCommand } = require('@aws-sdk/client-s3');
const fs = require('fs');
const stream = require('stream');
const { promisify } = require('util');
const pipeline = promisify(stream.pipeline);
async function downloadFile(key, destinationPath) {
const command = new GetObjectCommand({
Bucket: process.env.S3_BUCKET,
Key: key,
});
try {
const response = await s3Client.send(command);
const writeStream = fs.createWriteStream(destinationPath);
await pipeline(response.Body, writeStream);
console.log('Файл скачан:', destinationPath);
} catch (err) {
console.error('Ошибка скачивания:', err);
}
}
3. Получение списка объектов (ListObjectsV2)
Полезно для отображения файлов в корзине:
const { ListObjectsV2Command } = require('@aws-sdk/client-s3');
async function listFiles(prefix = '') {
const command = new ListObjectsV2Command({
Bucket: process.env.S3_BUCKET,
Prefix: prefix,
MaxKeys: 100,
});
try {
const response = await s3Client.send(command);
if (response.Contents) {
return response.Contents.map(item => ({
key: item.Key,
size: item.Size,
lastModified: item.LastModified,
}));
}
return [];
} catch (err) {
console.error('Ошибка получения списка:', err);
}
}
4. Удаление объекта (DeleteObject)
const { DeleteObjectCommand } = require('@aws-sdk/client