纯前端根据数据生成docx文档
基于docxtemplater库实现,通过jszip和file-saver实现打包下载
demo示例下载
项目主要使用的依赖以及版本
"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,这是收费的插件。
主要实现逻辑
-
将需要导出的docx模板,根据docxtemplater模板填充要求,vue2工程放到public/目录下
-
docxtemplater官网传送门:docxtemplater
-
docx模板常用配置如图所示:
-
{ name } 常量
-
{ %photo } 图片
-
{ #list } { / } 循环,在循环体中使用常量达到循环效果
-
-
* docx模板中,需要导出的图片,需要使用docxtemplater-image-module-free插件
2. 引入需要的依赖
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";
- 根据docx模板生成docx文档
- 生成文档主方法
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];
}
}
```