使用fflate生成Zip遇stream finishing错误,Zip文件损坏
问题原因与解决方案
核心原因
出现“ZIP Error: stream finishing”且Zip包为空/损坏,本质是异步操作顺序错误:
- pdf-lib生成子PDF的
save()方法是异步的,返回Promise;如果没等所有子PDF的生成、写入Zip操作完成,就提前结束了fflate的Zip流,会导致流在数据未完全写入时被终止,触发错误并生成无效Zip包。 - fflate的
ZipWriter要求所有文件写入操作完成后才能调用end(),否则会认为流提前结束,无法正确生成Zip结构。
不需要额外流处理钩子,只需修正异步流程
你不需要添加特殊钩子,关键是确保所有异步任务完成后再结束Zip流,以下是正确的处理逻辑:
- 等待所有子PDF生成并写入Zip:用
Promise.all并行处理每个子PDF的拆分、生成和写入操作,确保每个zip.add()都通过await等待完成。 - 最后统一结束Zip流:所有文件写入完成后,再调用
await zip.end(),确保Zip结构正确生成。
示例代码
const { ZipWriter } = require('fflate'); const { PDFDocument } = require('pdf-lib'); const fs = require('fs').promises; const { createWriteStream } = require('fs'); async function splitPdfAndZip() { // 读取源PDF文件 const sourcePdfBuffer = await fs.readFile('source.pdf'); const sourceDoc = await PDFDocument.load(sourcePdfBuffer); const totalPages = sourceDoc.getPageCount(); // 创建Zip写入流(以文件流为例) const outputStream = createWriteStream('split_pdfs.zip'); const zipWriter = new ZipWriter(outputStream); // 并行处理所有页面的拆分与写入 await Promise.all( Array.from({ length: totalPages }, async (_, pageIndex) => { // 生成单页PDF const singlePageDoc = await PDFDocument.create(); const [copiedPage] = await singlePageDoc.copyPages(sourceDoc, [pageIndex]); singlePageDoc.addPage(copiedPage); const pdfBytes = await singlePageDoc.save(); // 将生成的PDF写入Zip,必须await确保写入完成 await zipWriter.add(`page_${pageIndex + 1}.pdf`, pdfBytes); }) ); // 所有文件写入完成后,结束Zip流 await zipWriter.end(); outputStream.close(); } splitPdfAndZip().catch(err => console.error('操作失败:', err));
关键注意事项
- 必须
await zip.add():该方法返回Promise,不等待会导致写入操作未完成就结束流。 - 禁止提前关闭输出流:要等
zip.end()完成后再关闭输出流(如示例中的outputStream.close()),否则会截断Zip数据。 - 若使用内存流而非文件流:需确保
zip.end()完成后再提取内存中的Zip数据,避免数据不完整。
内容的提问来源于stack exchange,提问作者Lance Pollard
相关产品推荐
相关产品推荐

