const fs = require('fs') const path = require('path') const compressing = require('compressing') const rimrif = require('rimraf') const shell = require('shelljs'); const crypto = require('crypto'); /** * docx 替换模板字符串内容 * @example // 要替换内容的模板 let inputDocx = 'cs.docx' // 替换完成的docx文件 let outputDocx = 'dd.docx' // {{xx}} 处要替换的内容 let replaceData = { name: '替换name处的内容', age: '替换age处的内容', } replaceDocx(inputDocx, outputDocx, replaceData) */ function replaceDocx(inputDocxPath, outputDocxPath, options) { return new Promise((resolve,reject)=>{ // 解压出来的临时目录 let tempDir = path.join(__dirname , "temp") let md5 = crypto.createHash('md5'); let outmd5 = md5.update(outputDocxPath).digest('hex') let tempDocxPath = path.join(tempDir , outmd5) // 要替换的xml文件位置 let tempDocxXMLName = path.join(tempDocxPath,`word/document.xml`) // 压缩文件夹为文件 let dir_to_docx = (inputFilePath, outputFilePath) => { outputFilePath = path.join(tempDir,outputFilePath) // 创建压缩流 let zipStream = new compressing.zip.Stream() // 写出流 let outStream = fs.createWriteStream(outputFilePath) fs.readdir(inputFilePath, null, (err, files) => { if (!err) { files.map(file => path.join(inputFilePath, file)) .forEach(file => { zipStream.addEntry(file) }) } }) // 写入文件内容 zipStream.pipe(outStream) .on('close', () => { // 打包完成后删除临时目录 // console.log(tempDocxPath) shell.rm("-r",tempDocxPath) // rimrif.rimrafSync(tempDocxPath) resolve(true) }) } // 替换word/document.xml文件中{{xx}}处的内容 let replaceXML = (data, text) => { Object.keys(data).forEach(key => { text = text.replaceAll(`{{${key}}}`, data[key]) }) return text } // 解压docx文件替换内容重新打包成docx文件 compressing.zip.uncompress(inputDocxPath, tempDocxPath) .then(() => { // 读写要替换内容的xml文件 fs.readFile(tempDocxXMLName, null, (err, data) => { if (!err) { let text = data.toString() text = replaceXML(options, text) fs.writeFile(tempDocxXMLName, text, (err) => { if (!err) { dir_to_docx(tempDocxPath, outputDocxPath) } else { reject(err) } }) } else { reject(err) } }) }).catch(err => { reject(err) }) }) } module.exports.replaceDocx = replaceDocx