如何修改Node.js代码获取EPUB第二章前三段内容?
解决EPUB章节内容"File not found"问题并提取第二章前三段
问题根源分析
- 直接用
fs读取章节href对应的路径,忽略了EPUB内部文件的相对路径基准(相对于OPF文件位置) - Multer上传的文件路径未正确传递给epub.js,导致EPUB实例无法定位内部资源
- 章节href可能包含URL编码或特殊字符,直接拼接路径会出错
修复后的完整代码实现
const express = require('express'); const multer = require('multer'); const fs = require('fs'); const Epub = require('epubjs'); const { JSDOM } = require('jsdom'); // 用于解析HTML段落 const app = express(); // Multer配置:存储上传的EPUB文件到临时目录 const storage = multer.diskStorage({ destination: (req, file, cb) => { const uploadDir = './uploads'; if (!fs.existsSync(uploadDir)) { fs.mkdirSync(uploadDir); } cb(null, uploadDir); }, filename: (req, file, cb) => { cb(null, `${Date.now()}-${file.originalname}`); } }); const upload = multer({ storage }); // 处理EPUB上传和解析的接口 app.post('/upload-epub', upload.single('epub'), async (req, res) => { if (!req.file) { return res.status(400).send('No file uploaded'); } const epubPath = req.file.path; let book; try { // 初始化EPUB实例,使用文件路径直接加载 book = Epub(epubPath); await book.ready; // 等待EPUB解析完成 // 获取元数据(已成功部分,保留) const metadata = book.metadata; console.log('Metadata:', metadata); // 获取目录(已成功部分,保留) const toc = book.navigation.toc; console.log('Table of Contents:', toc); // 找到第二章(优先按标题匹配,无匹配则取索引1的项) const chapter2 = toc.find(item => item.label.includes('第二章')) || toc[1]; if (!chapter2) { return res.status(404).send('第二章未找到'); } // 通过epub.js的render方法获取章节内容,自动处理内部路径 const rendition = book.renderTo('div'); const chapterContent = await rendition.display(chapter2.href); // 使用JSDOM解析HTML,提取前三段文本 const dom = new JSDOM(chapterContent); const paragraphs = dom.window.document.querySelectorAll('p'); const firstThreeParagraphs = Array.from(paragraphs) .slice(0, 3) .map(p => p.textContent.trim()); // 返回结果 res.json({ metadata, chapter2Title: chapter2.label, firstThreeParagraphs }); } catch (error) { console.error('解析错误:', error); res.status(500).send(`解析失败: ${error.message}`); } finally { // 清理临时文件和EPUB实例资源 if (fs.existsSync(epubPath)) { fs.unlinkSync(epubPath); } book?.destroy(); } }); app.listen(3000, () => { console.log('Server running on port 3000'); });
关键修复点说明
- 放弃直接fs读取:使用epub.js内置的
renderTo和display方法获取章节内容,内部自动处理EPUB内部的相对路径和资源定位逻辑 - 等待解析完成:必须等待
book.ready状态后再操作目录和章节,确保所有EPUB资源解析完毕 - 精准提取段落:借助
jsdom解析章节HTML,直接定位<p>标签提取文本,避免手动处理HTML字符串的混乱 - 资源清理:在finally块中删除临时上传文件、销毁EPUB实例,避免内存泄漏和磁盘空间占用
依赖安装
确保安装所有必要依赖:
npm install express multer epubjs jsdom
内容的提问来源于stack exchange,提问作者SirBT
相关产品推荐
相关产品推荐

