| 13 | import { dirname, extname, join, basename } from 'node:path' |
| 14 | |
| 15 | export class ImageCompressTask implements TaskItem { |
| 16 | /** 需要处理的图片 */ |
| 17 | image: ImageInfoFetchTask |
| 18 | /** |
| 19 | * 本地存储路径 |
| 20 | */ |
| 21 | path: string = '' |
| 22 | backupPath: string = '' |
| 23 | /** sharp配置 */ |
| 24 | config: SharpConfig |
| 25 | /** 处理后的文件大小 */ |
| 26 | size: number = 0 |
| 27 | /** 格式化后的文件大小字符串 */ |
| 28 | sizeFormatted: string = '' |
| 29 | /** 处理后的图片宽度 */ |
| 30 | width: number = 0 |
| 31 | /** 处理后的图片高度 */ |
| 32 | height: number = 0 |
| 33 | /** 处理后的图片格式 */ |
| 34 | ext = '' |
| 35 | /** 压缩比 */ |
| 36 | compressionRatio: number = 0 |
| 37 | /** |
| 38 | * 缩小比例 |
| 39 | */ |
| 40 | sizePercentage: string = '' |
| 41 | /** 是否应用了水印 */ |
| 42 | hasWatermark: boolean = false |
| 43 | /** 是否应用了纹理 */ |
| 44 | hasTexture: boolean = false |
| 45 | /** 文件状态 */ |
| 46 | hasError: boolean = false |
| 47 | /** 错误信息 */ |
| 48 | errorMessage: string = '' |
| 49 | |
| 50 | constructor(image: ImageInfoFetchTask, config: SharpConfig, path: string, backupPath: string) { |
| 51 | this.image = image |
| 52 | this.config = config |
| 53 | this.path = path |
| 54 | this.backupPath = backupPath |
| 55 | } |
| 56 | |
| 57 | /** 格式化文件大小 */ |
| 58 | private formatFileSize(bytes: number): string { |
| 59 | if (bytes === 0) return '0 B' |
| 60 | const units = ['B', 'KB', 'MB', 'GB', 'TB'] |
| 61 | const k = 1024 |
| 62 | const i = Math.floor(Math.log(bytes) / Math.log(k)) |
| 63 | return `${parseFloat((bytes / Math.pow(k, i)).toFixed(2))} ${units[i]}` |
| 64 | } |
| 65 | |
| 66 | /** 获取压缩后的文件大小 */ |
| 67 | private async getFileSize(): Promise<boolean> { |
| 68 | try { |
| 69 | const stats = await stat(this.path) |
| 70 | this.size = stats.size |
| 71 | this.sizeFormatted = this.formatFileSize(stats.size) |
| 72 | if (this.image.size > 0) { |
nothing calls this directly
no outgoing calls
no test coverage detected