collect-system/apps/server/src/models/resource/processor/ImageProcessor.ts

63 lines
1.9 KiB
TypeScript
Raw Normal View History

2025-01-21 20:05:42 +08:00
import path from 'path';
2025-01-03 09:24:46 +08:00
import sharp from 'sharp';
2025-01-21 20:05:42 +08:00
import { FileMetadata, ImageMetadata, ResourceProcessor } from '../types';
import { Resource, ResourceStatus, db } from '@nice/common';
import { getUploadFilePath } from '@server/utils/file';
import { BaseProcessor } from './BaseProcessor';
2025-01-06 18:30:16 +08:00
2025-01-08 00:52:11 +08:00
export class ImageProcessor extends BaseProcessor {
2025-01-21 20:05:42 +08:00
constructor() {
super();
}
2025-01-03 09:24:46 +08:00
async process(resource: Resource): Promise<Resource> {
2025-01-08 00:52:11 +08:00
const { url } = resource;
const filepath = getUploadFilePath(url);
2025-01-03 09:24:46 +08:00
const originMeta = resource.metadata as unknown as FileMetadata;
if (!originMeta.mimeType?.startsWith('image/')) {
this.logger.log(`Skipping non-image resource: ${resource.id}`);
return resource;
}
try {
const image = sharp(filepath);
const metadata = await image.metadata();
if (!metadata) {
2025-01-08 00:52:11 +08:00
throw new Error(`Failed to get metadata for image: ${url}`);
2025-01-03 09:24:46 +08:00
}
// Create WebP compressed version
2025-01-21 20:05:42 +08:00
const compressedDir = this.createOutputDir(filepath, 'compressed');
const compressedPath = path.join(
compressedDir,
`${path.basename(filepath, path.extname(filepath))}.webp`,
);
2025-01-03 09:24:46 +08:00
await image
.webp({
quality: 80,
lossless: false,
2025-01-21 20:05:42 +08:00
effort: 5, // Range 0-6, higher means slower but better compression
2025-01-03 09:24:46 +08:00
})
.toFile(compressedPath);
const imageMeta: ImageMetadata = {
width: metadata.width || 0,
height: metadata.height || 0,
orientation: metadata.orientation,
space: metadata.space,
hasAlpha: metadata.hasAlpha,
2025-01-21 20:05:42 +08:00
};
2025-01-03 09:24:46 +08:00
const updatedResource = await db.resource.update({
where: { id: resource.id },
data: {
metadata: {
...originMeta,
2025-01-21 20:05:42 +08:00
...imageMeta,
},
},
2025-01-03 09:24:46 +08:00
});
return updatedResource;
} catch (error: any) {
throw new Error(`Failed to process image: ${error.message}`);
}
}
2025-01-21 20:05:42 +08:00
}