使用docxtemplater生成多份docx并打包Zip后文件无法打开的问题
问题:生成包含多份docx的Zip文件后,docx无法打开
使用docxtemplater生成单个.docx文件功能正常,但生成两份docx并加入PizZip实例打包成Zip后,Zip内的docx文件无法打开,提示“文件无效”。
原代码
import Docxtemplater from "docxtemplater"; import PizZip from "pizzip"; import PizZipUtils from "pizzip/utils"; import { saveAs } from "file-saver"; import expressionParser from "docxtemplater/expressions"; import JSZip from "jszip"; const storage = getStorage(); //New zip instance const outputZip = new PizZip(); function loadFile(url, callback) { PizZipUtils.getBinaryContent(url, callback); } export const renderRelianceForms = async () => { try { await getDownloadURL(ref(storage, "RS1PD.docx")).then((url) => { loadFile(url, function (error, content) { if (error) { throw error; } const zip = new PizZip(content); const doc = new Docxtemplater(zip, { paragraphLoop: true, linebreaks: true, parser: expressionParser }); doc.render({ // date: referral?.creation_date.toDate().toLocaleDateString(), }); const out = doc.getZip().generate({ type: "arraybuffer", compression: "DEFLATE", mimeType: "application/vnd.openxmlformats-officedocument.wordprocessingml.document", }); outputZip.file("Reliance Section 1 - Personal Details.docx", out, { base64: true }); console.log("success", out); }); }); await getDownloadURL(ref(storage, "RS1MP.docx")).then((url) => { loadFile(url, function (error, content) { if (error) { throw error; } const zip = new PizZip(content); const doc = new Docxtemplater(zip, { paragraphLoop: true, linebreaks: true, parser: expressionParser }); doc.render({ // date: referral?.creation_date.toDate().toLocaleDateString(), }); const out = doc.getZip().generate({ type: "arraybuffer", compression: "DEFLATE", mimeType: "application/vnd.openxmlformats-officedocument.wordprocessingml.document", }); outputZip.file("Reliance Section 1 - Missing Person Form.docx", out, { base64: true }); console.log("success", out); }); }); //OUTZIP const output = outputZip.generate({ type: "blob", compression: "DEFLATE", mimeType: "application/vnd.openxmlformats-officedocument.wordprocessingml.document", }); console.log(outputZip); saveAs(output, "Reliance.zip"); } catch (err) { console.error(err); } };
问题原因及修复方案
- 数据类型不匹配:生成docx时用
type: "arraybuffer",但添加到outputZip时指定了{ base64: true },导致二进制文件被错误编码。arraybuffer本身就是二进制数据,无需base64编码,需移除该选项。 - Zip文件MIME类型错误:生成最终Zip时,mimeType应使用
"application/zip",而非docx的MIME类型,否则会导致系统无法正确识别Zip格式。 - 异步流程混乱:原代码混用
await和回调函数,可能导致未完成两个docx的生成与添加就提前打包Zip。需将loadFile包装为Promise,统一用async/await处理异步操作,保证流程顺序。
修复后的代码
import Docxtemplater from "docxtemplater"; import PizZip from "pizzip"; import PizZipUtils from "pizzip/utils"; import { saveAs } from "file-saver"; import expressionParser from "docxtemplater/expressions"; const storage = getStorage(); // 将loadFile包装为Promise,适配async/await const loadFileAsync = (url) => { return new Promise((resolve, reject) => { PizZipUtils.getBinaryContent(url, (error, content) => { if (error) reject(error); else resolve(content); }); }); }; export const renderRelianceForms = async () => { try { const outputZip = new PizZip(); // 处理第一个docx const url1 = await getDownloadURL(ref(storage, "RS1PD.docx")); const content1 = await loadFileAsync(url1); const zip1 = new PizZip(content1); const doc1 = new Docxtemplater(zip1, { paragraphLoop: true, linebreaks: true, parser: expressionParser }); doc1.render({ // date: referral?.creation_date.toDate().toLocaleDateString(), }); const out1 = doc1.getZip().generate({ type: "arraybuffer", compression: "DEFLATE" }); outputZip.file("Reliance Section 1 - Personal Details.docx", out1); // 处理第二个docx const url2 = await getDownloadURL(ref(storage, "RS1MP.docx")); const content2 = await loadFileAsync(url2); const zip2 = new PizZip(content2); const doc2 = new Docxtemplater(zip2, { paragraphLoop: true, linebreaks: true, parser: expressionParser }); doc2.render({ // date: referral?.creation_date.toDate().toLocaleDateString(), }); const out2 = doc2.getZip().generate({ type: "arraybuffer", compression: "DEFLATE" }); outputZip.file("Reliance Section 1 - Missing Person Form.docx", out2); // 生成Zip文件,使用正确的MIME类型 const output = outputZip.generate({ type: "blob", compression: "DEFLATE", mimeType: "application/zip" }); saveAs(output, "Reliance.zip"); } catch (err) { console.error(err); } };
内容的提问来源于stack exchange,提问作者Yumma Tech
相关产品推荐
相关产品推荐

