/
viktorphp
/
back-socket
Обзор
Документация
Войти
/
viktorphp
/
back-socket
Код
Запросы
0
Задачи
Пакеты
0
Релизы
0
CI/CD
Аналитика
Безопасность
master
src/services/storage/storage.service.ts
122 строки
5 KB
Иванов Виктор Евгеньевич
feature-diary: добавить функционал дневника
11 апр 2026, 11:13
11 апр 2026, 11:13
8167a94
Код
Авторство
О чём код?
import { Injectable } from '@nestjs/common'; import { ConfigService } from '@nestjs/config'; import { S3Client, PutObjectCommand, GetObjectCommand, DeleteObjectCommand, } from '@aws-sdk/client-s3'; import { getSignedUrl } from '@aws-sdk/s3-request-presigner'; import { Readable } from 'stream'; /** * StorageService — сервис для работы с Yandex Object Storage. * Yandex Object Storage совместим с Amazon S3 API, * поэтому используем стандартный AWS SDK с указанием кастомного endpoint. * * Отвечает за: * - загрузку файлов в хранилище * - получение содержимого файла по ключу * - генерацию временных ссылок для скачивания * - удаление файлов */ @Injectable() export class StorageService { private readonly s3: S3Client; private readonly bucket: string; constructor(private readonly configService: ConfigService) { // Инициализируем S3-клиент с настройками Yandex Object Storage this.s3 = new S3Client({ endpoint: this.configService.get<string>('storage.endpoint'), region: this.configService.get<string>('storage.region'), credentials: { accessKeyId: this.configService.get<string>('storage.accessKeyId'), secretAccessKey: this.configService.get<string>( 'storage.secretAccessKey', ), }, // Yandex Object Storage требует path-style адресацию: // https://storage.yandexcloud.net/{bucket}/{key} // вместо виртуальной: https://{bucket}.storage.yandexcloud.net/{key} forcePathStyle: true, }); this.bucket = this.configService.get<string>('storage.bucket'); } /** * Загружает файл в Object Storage. * * @param key - Путь к файлу в хранилище (например: diary/userId/entryId/photo.jpg) * @param buffer - Содержимое файла в виде буфера * @param mimeType - MIME-тип файла (например: image/jpeg, application/pdf) */ async upload(key: string, buffer: Buffer, mimeType: string): Promise<void> { const command = new PutObjectCommand({ Bucket: this.bucket, Key: key, Body: buffer, ContentType: mimeType, }); await this.s3.send(command); } /** * Скачивает файл из Object Storage и возвращает его содержимое в виде буфера. * Используется, например, для передачи файла в OCR-сервис. * * @param key - Путь к файлу в хранилище * @returns Содержимое файла в виде Buffer */ async download(key: string): Promise<Buffer> { const command = new GetObjectCommand({ Bucket: this.bucket, Key: key, }); const response = await this.s3.send(command); // Тело ответа — это Node.js Readable stream, преобразуем в Buffer const stream = response.Body as Readable; return new Promise((resolve, reject) => { const chunks: Buffer[] = []; stream.on('data', (chunk) => chunks.push(Buffer.from(chunk))); stream.on('end', () => resolve(Buffer.concat(chunks))); stream.on('error', reject); }); } /** * Генерирует временную подписанную ссылку для скачивания файла. * Ссылка действительна в течение указанного времени (по умолчанию 1 час). * Это безопасный способ давать фронтенду доступ к приватным файлам. * * @param key - Путь к файлу в хранилище * @param expiresInSeconds - Время жизни ссылки в секундах (по умолчанию 3600 = 1 час) * @returns Подписанная URL-ссылка для скачивания файла */ async getSignedUrl(key: string, expiresInSeconds = 3600): Promise<string> { const command = new GetObjectCommand({ Bucket: this.bucket, Key: key, }); return getSignedUrl(this.s3, command, { expiresIn: expiresInSeconds }); } /** * Удаляет файл из Object Storage. * * @param key - Путь к файлу в хранилище */ async delete(key: string): Promise<void> { const command = new DeleteObjectCommand({ Bucket: this.bucket, Key: key, }); await this.s3.send(command); } }