如何使用Node.js结合DJView库的ddjvu工具转换所有DJVU文件为PDF
如何用Node.js结合ddjvu工具批量将DJVU文件转换为PDF?
嘿,这个需求我之前折腾过,刚好可以用Node.js配合DJView里的ddjvu工具搞定,还能控制并发数不让CPU跑满。下面是完整的实现方案,完全用Node.js内置模块,不用额外装第三方包:
前置准备
- 先安装DJView库,确保
ddjvu命令已经加入系统PATH(打开终端敲ddjvu --version能正常输出版本就说明没问题) - 确保你的机器上已经装了Node.js(v14+版本都可以)
完整实现代码
const fs = require('fs').promises; const os = require('os'); const { spawn } = require('child_process'); const path = require('path'); // 设置最大并发进程数:CPU核心数减1,避免占满系统资源 const MAX_CONCURRENCY = os.cpus().length - 1; // 当前正在运行的转换进程数 let currentRunning = 0; // 待转换的文件队列 const fileQueue = []; /** * 单个DJVU文件转换为PDF的函数 * @param {string} djvuPath - 源DJVU文件路径 * @returns {Promise<void>} */ async function chpoc(djvuPath) { return new Promise((resolve, reject) => { const pdfPath = path.join(path.dirname(djvuPath), `${path.basename(djvuPath, '.djvu')}.pdf`); // 启动ddjvu进程执行转换 const ddjvuProcess = spawn('ddjvu', ['-format=pdf', djvuPath, pdfPath]); // 监听进程退出事件 ddjvuProcess.on('exit', (code) => { if (code === 0) { console.log(`✅ 转换完成:${djvuPath} -> ${pdfPath}`); // 转换成功后删除原DJVU文件(谨慎操作,可注释掉这行先测试) fs.unlink(djvuPath) .then(() => console.log(`🗑️ 已删除原文件:${djvuPath}`)) .catch(err => console.error(`❌ 删除原文件失败:${err.message}`)); resolve(); } else { const errorMsg = `❌ 转换失败:${djvuPath},进程退出码:${code}`; console.error(errorMsg); reject(new Error(errorMsg)); } }); // 监听进程错误事件(比如找不到ddjvu命令) ddjvuProcess.on('error', (err) => { console.error(`❌ 启动转换进程失败:${err.message}`); reject(err); }); }); } /** * 处理队列中的文件,控制并发数 */ async function processQueue() { while (fileQueue.length > 0 && currentRunning < MAX_CONCURRENCY) { currentRunning++; const filePath = fileQueue.shift(); try { await chpoc(filePath); } catch (err) { // 转换失败也继续处理下一个文件 console.error(err.message); } finally { currentRunning--; // 处理完一个后,继续从队列取任务 processQueue(); } } } /** * 遍历指定目录,收集所有DJVU文件 * @param {string} dirPath - 要遍历的目录路径 */ async function collectDjvuFiles(dirPath) { try { const files = await fs.readdir(dirPath, { withFileTypes: true }); for (const file of files) { const fullPath = path.join(dirPath, file.name); if (file.isDirectory()) { // 递归遍历子目录 await collectDjvuFiles(fullPath); } else if (file.isFile() && path.extname(file.name).toLowerCase() === '.djvu') { fileQueue.push(fullPath); } } // 收集完文件后启动队列处理 processQueue(); } catch (err) { console.error(`❌ 遍历目录失败:${err.message}`); } } // 替换成你要处理的目录路径,比如 './djvu-files' const targetDir = './your-djvu-directory'; collectDjvuFiles(targetDir) .then(() => console.log(`📋 已开始处理目录:${targetDir}`)) .catch(err => console.error(err.message));
关键细节说明
- 并发控制:设置
MAX_CONCURRENCY为CPU核心数减1,这样既能利用多核优势,又不会让系统因为进程过多而卡顿。 - 转换逻辑:用
child_process.spawn启动ddjvu进程,指定输出格式为PDF,监听进程退出码判断转换是否成功。 - 删除原文件:代码里默认转换成功后删除原DJVU文件,如果你担心转换出错,可以先把这行代码注释掉,等确认转换结果没问题再打开。
- 递归遍历:支持遍历目标目录下的所有子目录,自动收集所有DJVU文件进行转换。
注意事项
- 如果你需要转换超大的DJVU文件,可能需要调整系统的进程资源限制,不过一般情况下默认设置就够用。
- 转换过程中不要手动中断Node.js进程,否则可能会生成不完整的PDF文件。
内容的提问来源于stack exchange,提问作者BigClap
相关产品推荐
相关产品推荐

