45 lines
1.2 KiB
TypeScript
45 lines
1.2 KiB
TypeScript
import path from 'path';
|
|
import fs from 'fs';
|
|
import logger from '../utils/logger';
|
|
import { THUMBNAIL_DIR } from '../middleware/upload';
|
|
|
|
let sharp: any = null;
|
|
try {
|
|
sharp = require('sharp');
|
|
} catch {
|
|
logger.warn('sharp not installed — thumbnail generation disabled');
|
|
}
|
|
|
|
async function generateThumbnail(filePath: string, mimeType: string): Promise<string | null> {
|
|
if (!sharp) return null;
|
|
if (!mimeType.startsWith('image/')) return null;
|
|
|
|
try {
|
|
const ext = path.extname(filePath);
|
|
const baseName = path.basename(filePath, ext);
|
|
const thumbPath = path.join(THUMBNAIL_DIR, `${baseName}_thumb.webp`);
|
|
|
|
await sharp(filePath)
|
|
.resize(200, 200, { fit: 'inside', withoutEnlargement: true })
|
|
.webp({ quality: 70 })
|
|
.toFile(thumbPath);
|
|
|
|
return thumbPath;
|
|
} catch (error) {
|
|
logger.error('Thumbnail generation failed', { filePath, error });
|
|
return null;
|
|
}
|
|
}
|
|
|
|
function deleteFile(filePath: string): void {
|
|
try {
|
|
if (fs.existsSync(filePath)) {
|
|
fs.unlinkSync(filePath);
|
|
}
|
|
} catch (error) {
|
|
logger.error('File deletion failed', { filePath, error });
|
|
}
|
|
}
|
|
|
|
export default { generateThumbnail, deleteFile };
|