106 lines
3.4 KiB
TypeScript

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<Buffer> => {
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;
}
};
*/