前端生成word的方法还挺多的,在开始这项功能之前应该先选一份合适自己的框架,笔者最开始使用的就是docxtemplater框架,优点就是npm上面周下载量挺多的,看文档示例还有网友写的文章挺简单的上手很快,缺点就是商业化的框架要收费,如果你的word比较复杂有图片啥的,图片模板就是要收费的。后来发现了一个比较小众的 docx-templates(https://github.com/guigrpa/docx-templates),虽然小众但是能满足自己的需求就行。目前这个框架网上的资料除了github上的文档几乎没有任何资料,这里简单记录一下用法。有时间再来补充踩过的坑,这个坑主要都在图片合成那边。框架本身没啥问题。
要做的功能如下图是一个网页,点击下载生成一个一样的word,后端因为一些原因,现在生成word的功能放在了前端。这个功能其实不难,难的是在word中插入图片,一个是地图位置的图片,另一个是一个图片列表含有多张图片,除此之外你要合成一个蓝色的header头,这个图片后端返回的是一个图片地址。
这是vue项目
安装:
cnpm i docx-templates -S
// jszip-utils 用于获取模板文件 template.docx,讲道理浏览器是不允许未经用户允许读取本地数据和写入数据到本地,因为这违反了浏览器的安全策略,所以有这个库我也很意外,要不然这个功能用这个库可能搞不起来,除非让用户主动上传模板,github给出的也是用户主动上传模板。这个文件我放在public目录底下,具体template.docx 文件样式我截图放在最后
cnpm i jszip-utils -S
import JSZipUtils from 'jszip-utils';
/* 生成word */
const { createReport } = require('docx-templates');
// 点击下载按钮执行的word合成代码,这里只留了 creator 和 getMapPicture() 地图图片作为示例
JSZipUtils.getBinaryContent(
'./template.docx',
async (error, template) => {
// 抛出异常
if (error) {
throw error;
}
const report = await createReport({
template,
data: {
//这个是你要放在 template.docx模板中的字段,这个变量后面会插入到template.docx模板中
creator: 'zhangsan',
},
// 这个对象里面的函数会在合成模板之前被执行
additionalJsContext: {
// 返回的格式如下, res 是图片 base64 编码
getMapPicture: async () => {
const res = await this.getMapPicBase64(ticketInfo);
return {
width: 6,
height: 6,
data: res,
extension: '.png'
};
},
},
// 这个属性定义了模板中变量的边界,例如template.docx中插入变量就可以使用{ creator }
cmdDelimiter: ['{', '}']
});
this.saveDataToFile(
report,
'123.docx',//文件名称
'application/vnd.openxmlformats-officedocument.wordprocessingml.document'
);
}
);
}
// 下载按钮方法结束
/* 下载word文件 */
async saveDataToFile(data, fileName, mimeType) {
const blob = new Blob([data], { type: mimeType });
const url = window.URL.createObjectURL(blob);
this.downloadURL(url, fileName, mimeType);
setTimeout(() => {
window.URL.revokeObjectURL(url);
}, 1000);
},
async downloadURL(data, fileName) {
const a = document.createElement('a');
a.href = data;
a.download = fileName;
document.body.appendChild(a);
a.style = 'display: none';
a.click();
a.remove();
},
template.docx 模板,这几乎是我模板原件了