import sharp from 'sharp'; import fs from 'fs'; /** * 压缩图片到目标大小左右 * @param inputPath 输入文件路径 * @param outputPath 输出文件路径 * @param targetSize 目标大小(字节),默认100KB */ export async function compressImage( inputPath: string, outputPath: string, targetSize: number = 100 * 1024 ): Promise<{ success: boolean; finalSize?: number; error?: string }> { try { let quality = 80; let compressedSize = targetSize + 1; // 获取图片信息 const metadata = await sharp(inputPath).metadata(); let width = metadata.width; let height = metadata.height; // 如果图片尺寸较大,先调整尺寸 if (width && height && (width > 2000 || height > 2000)) { width = Math.round(width * 0.5); height = Math.round(height * 0.5); } while (compressedSize > targetSize && quality > 10) { await sharp(inputPath) .resize(width, height, { fit: 'inside', withoutEnlargement: true, }) .jpeg({ quality: quality, mozjpeg: true, }) .toFile(outputPath); // 获取压缩后文件大小 const stats = fs.statSync(outputPath); compressedSize = stats.size; // 如果仍然大于目标大小,降低质量继续压缩 if (compressedSize > targetSize) { quality -= 15; if (quality < 10) quality = 10; } } return { success: true, finalSize: compressedSize }; } catch (error) { return { success: false, error: error instanceof Error ? error.message : '压缩失败', }; } }