安装依赖
npm install docxtemplater pizzip --save
npm install jszip-utils --save
npm install jszip --save
npm install file-saver --save
npm install angular-expressions --save
npm install image-size --save
封装辅助函数
import PizZip from "pizzip";
import docxtemplater from "docxtemplater";
import JSZipUtils from "jszip-utils";
import { saveAs } from "file-saver";
/**
* 将base64格式的数据转为ArrayBuffer
* @param {Object} dataURL base64格式的数据
*/
function base64DataURLToArrayBuffer(dataURL) {
const base64Regex = /^data:image\/(png|jpg|jpeg|svg|svg\+xml);base64,/;
if (!base64Regex.test(dataURL)) {
return false;
}
const stringBase64 = dataURL.replace(base64Regex, "");
let binaryString;
if (typeof window !== "undefined") {
binaryString = window.atob(stringBase64);
} else {
binaryString = new Buffer(stringBase64, "base64").toString("binary");
}
const len = binaryString.length;
const bytes = new Uint8Array(len);
for (let i = 0; i < len; i++) {
const ascii = binaryString.charCodeAt(i);
bytes[i] = ascii;
}
return bytes.buffer;
}
/**
* 导出word,支持图片
* @param {Object} tempDocxPath 模板文件路径
* @param {Object} wordData 导出数据
* @param {Object} fileName 导出文件名
* @param {Object} imgSize 自定义图片尺寸
*/
export const exportWord = async (tempDocxPath, wordData, fileName, imgSize) => {
// 这里要引入处理图片的插件
let asyncImageModule2 = await import("docxtemplater-image-module-free");
var ImageModule = asyncImageModule2.default;
const expressions = import("angular-expressions");
// 读取并获得模板文件的二进制内容
JSZipUtils.getBinaryContent(tempDocxPath, async function (error, content) {
if (error) {
throw error;
}
let asyncExpressions = await expressions;
asyncExpressions.filters.size = function (input, width, height) {
return {
data: input,
size: [width, height],
};
};
// 图片处理
let opts = {};
opts = {
// 图像是否居中
centered: false,
};
opts.getImage = (chartId) => {
return base64DataURLToArrayBuffer(chartId);
};
opts.getSize = function (img, tagValue, tagName) {
// 自定义指定图像大小
if (imgSize.hasOwnProperty(tagName)) {
return imgSize[tagName];
} else {
return [600, 350];
}
};
// 创建一个PizZip实例,内容为模板的内容
let zip = new PizZip(content);
// 创建并加载docxtemplater实例对象
let doc = new docxtemplater();
doc.attachModule(new ImageModule(opts));
doc.loadZip(zip);
doc.setData(wordData);
try {
// 用模板变量的值替换所有模板变量
doc.render();
} catch (error) {
// 抛出异常
let e = {
message: error.message,
name: error.name,
stack: error.stack,
properties: error.properties,
};
console.log(
JSON.stringify({
error: e,
})
);
throw error;
}
// 生成一个代表docxtemplater对象的zip文件(不是一个真实的文件,而是在内存中的表示)
let out = doc.getZip().generate({
type: "blob",
mimeType:
"application/vnd.openxmlformats-officedocument.wordprocessingml.document",
});
// 将目标文件对象保存为目标类型的文件,并命名
saveAs(out, fileName);
});
};
public创建word.docx模板
<el-form :model="form">
<el-form-item label="名字">
<el-input v-model="form.name" />
</el-form-item>
<el-form-item label="日期">
<el-input v-model="form.date" />
</el-form-item>
<el-form-item label="上传图片">
<el-input v-model="form.imgUrl" />
<!-- <el-upload
v-model:file-list="fileList"
multiple
class="upload-demo"
:auto-upload="false"
@submit="customRequest"
>
<el-icon><Plus /></el-icon>
</el-upload> -->
<input type="file" @change="customRequest" />
</el-form-item>
<el-form-item>
<el-button type="primary" @click="exportWordFile">导出word</el-button>
</el-form-item>
</el-form>
js
import { exportWord } from "./imgF.js";
import { ref } from "vue";
let form = ref({
name: "testExportWordFile",
date: new Date().toLocaleTimeString(),
imgUrl: "",
});
const fileList = ref([]);
const dialogImageUrl = ref("");
const dialogVisible = ref(false);
let customRequest = (data1) => {
let file = data1.target.files[0];
var reader = new FileReader();
reader.readAsDataURL(file);
reader.onload = () => {
form.value.imgUrl = reader.result;
};
reader.onerror = function (error) {
console.log("Error: ", error);
};
};
// fn
let exportWordFile = () => {
let imgSize = {
imgUrl: [165, 165],
};
exportWord(
"./public/word.docx",
form.value,
`${new Date().toLocaleDateString()}.docx`,
imgSize
);
};