Files
DeEarthX-CE/backend/src/dearth/utils/FileExtractor.ts
15736060610 5c278e1925
Some checks failed
CI/CD / Code Check (push) Has been cancelled
CI/CD / Build Windows (push) Has been cancelled
支持大文件
2026-03-15 09:02:02 +08:00

72 lines
2.1 KiB
TypeScript

import fs from "node:fs";
import crypto from "node:crypto";
import path from "node:path";
import { JarParser } from "../../utils/jar-parser.js";
import { logger } from "../../utils/logger.js";
import { IFileInfo } from "../types.js";
export class FileExtractor {
private readonly modsPath: string;
constructor(modsPath: string) {
this.modsPath = path.isAbsolute(modsPath) ? modsPath : path.resolve(modsPath);
}
async extractFilesInfo(): Promise<IFileInfo[]> {
const jarFiles = this.getJarFiles();
const files: IFileInfo[] = [];
logger.info("获取文件信息", { 文件数量: jarFiles.length });
for (const jarFilename of jarFiles) {
const fullPath = path.join(this.modsPath, jarFilename);
try {
const hash = await this.calculateFileHash(fullPath);
const mixins = await JarParser.extractMixinsFromFile(fullPath);
const infos = await JarParser.extractModInfoFromFile(fullPath);
files.push({
filename: fullPath,
hash,
mixins,
infos,
});
logger.debug("文件已处理", { 文件名: fullPath, 绝对路径: path.resolve(fullPath), Mixin数量: mixins.length });
} catch (error: any) {
logger.error("处理文件时出错", { 文件名: fullPath, 错误: error.message });
}
}
logger.debug("文件信息收集完成", { 已处理文件: files.length });
return files;
}
private async calculateFileHash(filePath: string): Promise<string> {
return new Promise((resolve, reject) => {
const hash = crypto.createHash('sha1');
const stream = fs.createReadStream(filePath);
stream.on('data', (chunk) => {
hash.update(chunk);
});
stream.on('end', () => {
resolve(hash.digest('hex'));
});
stream.on('error', (error) => {
reject(error);
});
});
}
private getJarFiles(): string[] {
if (!fs.existsSync(this.modsPath)) {
fs.mkdirSync(this.modsPath, { recursive: true });
}
return fs.readdirSync(this.modsPath).filter(f => f.endsWith(".jar"));
}
}