import { S3Client, PutObjectCommand, GetObjectCommand} from '@aws-sdk/client-s3'; import { getSignedUrl } from '@aws-sdk/s3-request-presigner'; import multer from 'multer'; import sharp from 'sharp'; import { imageResolutions } from '../config/imageResolutions'; // Функция для создания клиента S3 export const createS3Client = (region: string, endpoint: string, accessKeyId: string, secretAccessKey: string) => { return new S3Client({ region: region, endpoint: endpoint, credentials: { accessKeyId: accessKeyId, secretAccessKey: secretAccessKey, } }); }; // Функция для изменения размеров и оптимизации изображения const resizeAndOptimizeImage = async (buffer: Buffer, width: number, height: number, quality: number): Promise => { return await sharp(buffer) .resize(width, height, { fit: sharp.fit.inside }) .webp({ quality }) .toBuffer(); }; // Функция для получения конфигурации Multer-S3 export const getMulterS3Config = ( s3Client: S3Client, bucketName: string ) => { return multer({ storage: multer.memoryStorage(), // Храним файл в памяти перед обработкой fileFilter: (req, file, cb) => { if (!file.mimetype.startsWith('image/')) { return cb(new Error('Разрешены только файлы изображений!')); } cb(null, true); }, }).single('file'); // Обрабатываем один файл }; // Функция для загрузки файла в S3 после оптимизации export const uploadToS3 = async ( s3Client: S3Client, bucketName: string, folder: string, file: Express.Multer.File, resolutionId: string, quality: number ) => { try { const selectedResolution = imageResolutions.find(r => r.id === resolutionId); if (!selectedResolution) { throw new Error('Недопустимое разрешение изображения'); } // Оптимизируем изображение const optimizedBuffer = await resizeAndOptimizeImage( file.buffer, selectedResolution.width, selectedResolution.height, quality ); // Генерируем уникальное имя файла const uniqueSuffix = Date.now() + '-' + Math.round(Math.random() * 1e9); const fileNameWithoutExt = file.originalname.replace(/\.[^.]+$/, ''); const fileName = `${folder}/${uniqueSuffix}-${fileNameWithoutExt}.webp`; // Загружаем файл в S3 const command = new PutObjectCommand({ Bucket: bucketName, Key: fileName, Body: optimizedBuffer, ContentType: file.mimetype, ACL: 'public-read', }); await s3Client.send(command); // Возвращаем URL загруженного файла return `https://${bucketName}.s3.regru.cloud/${fileName}`; } catch (error) { throw new Error(`Ошибка загрузки файла в S3: ${error}`); } }; /* export const getImage = async (imageId: string, bucketName: string) => { try { const command = new GetObjectCommand({ Bucket: bucketName, Key: `uploads/${imageId}` }); const url = await getSignedUrl(s3Client, command, { expiresIn: 3600 }); return { url }; } catch (error) { throw error; } }; */