import { dirExists } from "#utils"; import { files_insert, files_insert_link_epub } from "#db"; import crypto from "crypto"; import fs from "node:fs"; import logger from "#logger"; export async function saveImgs(epub, uploadPath, book_id, author_id) { dirExists(uploadPath + "image/"); let imgs = epub.listImage(); if (imgs.length) { const imgRes = await Promise.allSettled( imgs.map((img) => { return epub.getImageAsync(img.id); }) ); // 过滤数据 const imgs_fulfilled = imgs .map((img, index) => { const img_fulfilled = imgRes[index]; if (img_fulfilled.status === "fulfilled") { const [img_data, img_mimeType] = img_fulfilled.value; return { ...img, index, img_data, img_mimeType, }; } return false; }) .filter((elm) => elm); await Promise.allSettled( imgs_fulfilled.map(async (elm) => { const img_md5 = await calculateMD5FromBuffer(elm.img_data); const imgUploadPath = uploadPath + "image/" + img_md5; const params = { file_id: img_md5, md5: img_md5, mimetype: elm.img_mimeType, size: elm.img_data.length, name: elm.id, path: elm.href, source_id: elm.id, }; fs.writeFile(imgUploadPath, elm.img_data, (err) => { if (err) { logger.error("Error writing Img file:", err); } else { logger.info("Img data saved to " + img_md5); } }); await files_insert(params); return await files_insert_link_epub({ file_id: img_md5, book_id, author_id, }); }) ); } } export function calculateMD5(filePath) { return new Promise((resolve, reject) => { try { const hash = crypto.createHash("md5"); const stream = fs.createReadStream(filePath); stream.on("data", (chunk) => { hash.update(chunk); }); stream.on("end", () => { resolve(hash.digest("hex")); }); } catch (err) { resolve(""); } }); } export async function calculateMD5FromStream(fileStream) { return new Promise((resolve, reject) => { const hash = crypto.createHash("md5"); // 错误处理 fileStream.on("error", (err) => { console.error("Error reading file stream:", err); reject("生成失败!"); // 使用 reject 传递错误信息 }); // 监听 'data' 事件,更新 MD5 哈希 fileStream.on("data", (chunk) => { hash.update(chunk); }); // 监听 'end' 事件,文件读取完毕后输出 MD5 值 fileStream.on("end", () => { const md5 = hash.digest("hex"); resolve(md5); // 正常计算完 MD5 后 resolve }); }); } export function calculateMD5FromBuffer(buffer) { return new Promise((resolve, reject) => { try { // 使用 crypto 计算 MD5 const hash = crypto.createHash("md5"); hash.update(buffer); // 直接更新 hash const md5 = hash.digest("hex"); // 获取最终的 MD5 值 resolve(md5); // 返回 MD5 } catch (err) { console.error("Error calculating MD5:", err); reject("生成失败!"); } }); } const formatSize = (bytes) => { if (bytes < 1024) return `${bytes} 字节`; else if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(2)} KB`; else if (bytes < 1024 * 1024 * 1024) return `${(bytes / (1024 * 1024)).toFixed(2)} MB`; else return `${(bytes / (1024 * 1024 * 1024)).toFixed(2)} GB`; };