@zzclub/z-cli
Version:
all-in-one 工具箱,专为提升日常及工作效率而生
137 lines • 4.82 kB
JavaScript
import { readdirSync, statSync } from 'node:fs';
import { join, dirname, basename, extname } from 'node:path';
import { SUPPORTED_FORMATS } from './types.js';
import { logger, formatFileSize, formatCompressionRatio } from '../../core/logger.js';
/**
* 文件处理器
*/
export class FileProcessor {
compressor;
constructor(compressor) {
this.compressor = compressor;
}
/**
* 处理单个文件或目录
*/
async process(inputPath, options) {
const stat = statSync(inputPath);
if (stat.isFile()) {
return this.processFile(inputPath, options);
}
if (stat.isDirectory() && options.recursive) {
return this.processDirectory(inputPath, options);
}
throw new Error('输入路径必须是文件,或者是目录(需要 --recursive 参数)');
}
/**
* 处理单个文件
*/
async processFile(filePath, options) {
// 检查文件格式
const ext = extname(filePath).toLowerCase();
if (!SUPPORTED_FORMATS.includes(ext)) {
throw new Error(`不支持的文件格式: ${ext},支持的格式: ${SUPPORTED_FORMATS.join(', ')}`);
}
// 确定输出路径
const outputPath = this.getOutputPath(filePath, options);
logger.start(`正在压缩: ${filePath}`);
const result = await this.compressor.compress(filePath, outputPath, options);
if (result.success) {
logger.success(`压缩成功: ${formatFileSize(result.originalSize)} → ${formatFileSize(result.compressedSize)} ` +
`(减少 ${formatCompressionRatio(result.compressionRatio)})`);
}
else {
logger.error(`压缩失败: ${result.error}`);
}
return {
total: 1,
success: result.success ? 1 : 0,
failed: result.success ? 0 : 1,
totalOriginalSize: result.originalSize,
totalCompressedSize: result.compressedSize,
averageCompressionRatio: result.compressionRatio,
results: [result],
};
}
/**
* 处理目录
*/
async processDirectory(dirPath, options) {
const files = this.collectImageFiles(dirPath, options.recursive || false);
if (files.length === 0) {
logger.warn(`目录中没有找到支持的图片文件: ${dirPath}`);
return this.emptyStats();
}
logger.info(`找到 ${files.length} 个图片文件`);
const stats = this.emptyStats();
for (const file of files) {
const fileStats = await this.processFile(file, options);
this.mergeStats(stats, fileStats);
}
return stats;
}
/**
* 收集目录中的图片文件
*/
collectImageFiles(dirPath, recursive) {
const files = [];
const entries = readdirSync(dirPath, { withFileTypes: true });
for (const entry of entries) {
const fullPath = join(dirPath, entry.name);
if (entry.isFile()) {
const ext = extname(entry.name).toLowerCase();
if (SUPPORTED_FORMATS.includes(ext)) {
files.push(fullPath);
}
}
else if (entry.isDirectory() && recursive) {
files.push(...this.collectImageFiles(fullPath, recursive));
}
}
return files;
}
/**
* 确定输出路径
*/
getOutputPath(inputPath, options) {
const dir = dirname(inputPath);
const base = basename(inputPath, extname(inputPath));
const ext = extname(inputPath);
if (options.overwrite) {
return inputPath;
}
const outputDir = options.outputDir || dir;
return join(outputDir, `${base}-compressed${ext}`);
}
/**
* 创建空统计
*/
emptyStats() {
return {
total: 0,
success: 0,
failed: 0,
totalOriginalSize: 0,
totalCompressedSize: 0,
averageCompressionRatio: 0,
results: [],
};
}
/**
* 合并统计数据
*/
mergeStats(target, source) {
target.total += source.total;
target.success += source.success;
target.failed += source.failed;
target.totalOriginalSize += source.totalOriginalSize;
target.totalCompressedSize += source.totalCompressedSize;
target.results.push(...source.results);
// 重新计算平均压缩率
if (target.totalOriginalSize > 0) {
target.averageCompressionRatio =
((target.totalOriginalSize - target.totalCompressedSize) / target.totalOriginalSize) * 100;
}
}
}
//# sourceMappingURL=file-processor.js.map