使用Node.js的pdf-poppler转换MongoDB存储的PDF为图片遇路径问题
解决MongoDB存储的PDF转图片(pdf-poppler适配方案)
我明白你被这个问题卡了一周的烦躁——pdf-poppler确实只认本地文件路径,但MongoDB里的PDF要么是二进制Buffer要么存在GridFS里,根本拿不到现成的本地路径。核心思路其实很简单:把MongoDB里的二进制数据先写到本地临时文件,用完再删掉,这样就能完美适配这个库的要求了。
下面分两种常见存储场景给你具体实现:
场景1:MongoDB直接存PDF的Buffer数据
如果你的MongoDB文档里直接存了PDF的Buffer(比如字段叫pdfData),可以这么做:
- 从MongoDB读取Buffer数据
- 用
fs模块把Buffer写入一个唯一命名的临时文件(避免文件名冲突) - 把临时文件路径传给pdf-poppler处理
- 转换完成后立刻删除临时文件,避免占用磁盘空间
示例代码:
const path = require('path'); const pdf = require('pdf-poppler'); const fs = require('fs').promises; const { v4: uuidv4 } = require('uuid'); // 生成唯一临时文件名 const mongoose = require('mongoose'); // 假设用mongoose操作MongoDB // 定义你的PDF数据模型 const PdfModel = mongoose.model('Pdf', new mongoose.Schema({ pdfData: Buffer, // 其他业务字段... })); async function convertPdfFromMongo() { let tempFilePath; try { // 1. 从MongoDB读取目标PDF的Buffer const pdfDoc = await PdfModel.findById('你的文档ID'); if (!pdfDoc || !pdfDoc.pdfData) { throw new Error('未找到对应的PDF数据'); } // 2. 创建临时文件路径(用uuid确保文件名唯一) tempFilePath = path.join(__dirname, 'temp', `${uuidv4()}.pdf`); // 确保temp目录存在,不存在就创建 await fs.mkdir(path.join(__dirname, 'temp'), { recursive: true }); // 3. 将Buffer写入临时文件 await fs.writeFile(tempFilePath, pdfDoc.pdfData); // 4. 调用pdf-poppler执行转换 const opts = { format: 'jpeg', out_dir: path.join(__dirname, 'output'), out_prefix: 'converted_pdf', page: null // 转换所有页面,指定数字可转换单页 }; await pdf.convert(tempFilePath, opts); console.log('PDF转图片成功!'); } catch (err) { console.error('转换过程出错:', err); } finally { // 不管成功失败,都要清理临时文件 if (tempFilePath) { try { await fs.unlink(tempFilePath); } catch (cleanErr) { console.error('清理临时文件失败:', cleanErr); } } } } // 触发转换 convertPdfFromMongo();
场景2:用GridFS存储PDF文件
如果你的PDF是用MongoDB的GridFS存储的(适合大文件),可以用GridFSBucket读取文件流,再写入本地临时文件:
示例代码:
const path = require('path'); const pdf = require('pdf-poppler'); const fs = require('fs').promises; const { createWriteStream } = require('fs'); const { v4: uuidv4 } = require('uuid'); const mongoose = require('mongoose'); async function convertGridFSPdf() { let tempFilePath; try { // 初始化GridFSBucket const bucket = new mongoose.mongo.GridFSBucket(mongoose.connection.db, { bucketName: 'pdf_files' // 你的GridFS桶名称 }); // 1. 从GridFS获取文件流 const fileId = new mongoose.Types.ObjectId('你的GridFS文件ID'); const downloadStream = bucket.openDownloadStream(fileId); // 2. 创建临时文件路径 tempFilePath = path.join(__dirname, 'temp', `${uuidv4()}.pdf`); await fs.mkdir(path.join(__dirname, 'temp'), { recursive: true }); // 3. 将GridFS流写入临时文件 await new Promise((resolve, reject) => { const writeStream = createWriteStream(tempFilePath); downloadStream.pipe(writeStream); writeStream.on('finish', resolve); writeStream.on('error', reject); }); // 4. 执行PDF转图片 const opts = { format: 'jpeg', out_dir: path.join(__dirname, 'output'), out_prefix: 'gridfs_converted' }; await pdf.convert(tempFilePath, opts); console.log('GridFS存储的PDF转图片成功!'); } catch (err) { console.error('转换出错:', err); } finally { // 清理临时文件 if (tempFilePath) { try { await fs.unlink(tempFilePath); } catch (cleanErr) { console.error('清理临时文件失败:', cleanErr); } } } } convertGridFSPdf();
额外提醒
- 记得安装依赖:
npm install pdf-poppler uuid mongoose - 临时文件目录要确保有读写权限,也可以用
node-cleanup包在进程退出时自动清理残留的临时文件 - 如果是超大PDF,用流的方式处理(比如GridFS的示例)能避免内存溢出问题
内容的提问来源于stack exchange,提问作者Asma_Kh
相关产品推荐
相关产品推荐

