# docx-create **Repository Path**: oneplusone666/docx-create ## Basic Information - **Project Name**: docx-create - **Description**: 纯前端根据数据生成docx文档 - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2024-12-31 - **Last Updated**: 2024-12-31 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README ### 纯前端根据数据生成docx文档 基于docxtemplater库实现,通过jszip和file-saver实现打包下载 ### demo示例下载 [gitee地址:docx-create](https://gitee.com/oneplusone666/docx-create) #### 项目主要使用的依赖以及版本 ```json "docxtemplater": "^3.55.8", "docxtemplater-image-module-free": "^1.1.1", "file-saver": "^2.0.5", "jszip": "^3.10.1", "jszip-utils": "^0.1.0", "pizzip": "^3.1.7", ``` - 依赖安装需要注意,加载图片时需要使用docxtemplater-image-module-free,不要使用docxtemplater-image-module,这是收费的插件。 #### 主要实现逻辑 1. 将需要导出的docx模板,根据docxtemplater模板填充要求,vue2工程放到public/目录下 - docxtemplater官网传送门:[docxtemplater](https://docxtemplater.com/) - docx模板常用配置如图所示: - { name } 常量 - { %photo } 图片 - { #list } { / } 循环,在循环体中使用常量达到循环效果 ![image-20211029161152470](https://gitee.com/oneplusone666/img/raw/master/img/image-20211029161152470.png) - docx模板中,需要导出的图片,需要使用docxtemplater-image-module-free插件 2. 引入需要的依赖 ```js import Docxtemplater from 'docxtemplater'; import JSZip from 'jszip'; import JSZipUtils from 'jszip-utils'; import { saveAs } from 'file-saver'; import PizZip from "pizzip"; import PizZipUtils from "pizzip/utils/index.js"; import ImageModule from "docxtemplater-image-module-free"; ``` 3. 根据docx模板生成docx文档 - 生成文档主方法 ```JS JSZipUtils.getBinaryContent(this.fileTemplete + '.docx',async (error, content) => { // 抛出异常 if (error) throw error; if (this.exportData.length === 0) { console.log("没有文件") } //单文件 if (this.exportData.length === 1) { const zip = new PizZip(content); const doc = new Docxtemplater(zip, { //图片加载使用的插件 modules: [new ImageModule(imageOpts)], paragraphLoop: true, linebreaks: true, }); //exportData是导出的数据 //这里只能使用renderAsync异步渲染,因为图片加载是异步的 await doc.renderAsync(this.exportData[0]); const out = doc.getZip().generate({ type: "blob", mimeType: "application/vnd.openxmlformats-officedocument.wordprocessingml.document" }); saveAs(out, this.exportData[0].fileName + '.docx'); } else { const _zip = new JSZip(); //导出压缩包文件名 const outDocName = this.zipName Promise.all( this.exportData.map(async (item, index) => { const zip = new PizZip(content); const doc = new Docxtemplater(zip, { modules: [new ImageModule(imageOpts)], paragraphLoop: true, linebreaks: true, }); // 这里只能使用renderAsync异步渲染,因为图片加载是异步的 await doc.renderAsync({ ...item }); // 生成单个文档的 Blob const out = doc.getZip().generate({ type: "blob", mimeType: "application/vnd.openxmlformats-officedocument.wordprocessingml.document", }); // 将生成的文件添加到 zip 中 _zip.file(`${index + 1}-${item.fileName}.doc`, out); }) ).then(() => { // 所有文档处理完成后,生成 ZIP 文件并下载 _zip.generateAsync({ type: "blob" }).then((content) => { saveAs(content, `${outDocName}.zip`); }); }).catch((error) => { console.error("生成文档失败:", error); }); } }) ``` - imageOpts配置 ``` const imageOpts = { //获取图片数据,这里使用了异步获取,也可以直接返回图片数据 getImage: async function (imageUrl) { const response = await fetch(imageUrl); const arrayBuffer = await response.arrayBuffer(); console.log("arrayBuffer", arrayBuffer) return Buffer.from(arrayBuffer); // 转为 Buffer }, //获取图片大小,这里只使用了固定比例,也可以异步获取 getSize: () => { const width = 100; // px const height = (200 / 16) * 9; // 假设宽高比为 16:9 return [width, height]; } } ```