原文参考:vue 导出word文档(包括图片)_vue 生成word-CSDN博客
由于我使用ELEMTN UI或其他UI文件上传组件,所以尝试多次,未能成功。后来发现是原博主在上传时在组件中已经转为base64格式,所以以下附上图片转base64格式的JS,供参考。
第一步安装依赖。
第二步创建两个JS文件,一个供图片转换为base64格式,一个供导出word。
export function imageToBase64(imagePath) {
return new Promise((resolve, reject) => {
// 创建一个新的 Image 对象
const img = new Image();
// 当图像加载完成后执行此操作
img.onload = function() {
// 创建一个 canvas 元素
const canvas = document.createElement('canvas');
const ctx = canvas.getContext('2d');
// 设置 canvas 的尺寸与图像相同
canvas.width = img.width;
canvas.height = img.height;
// 在 canvas 上绘制图像
ctx.drawImage(img, 0, 0);
// 获取图像数据的 base64 编码
const base64 = canvas.toDataURL('image/png'); // 可以修改格式,这里是 PNG 格式
// 返回 base64 数据
resolve(base64);
};
// 图像加载失败时执行此操作
img.onerror = function(error) {
reject(error);
};
// 设置图像的路径为传入的图像路径
img.src = imagePath;
});
}
全部使用原文代码在opts.getSize = function (img, tagValue, tagName) {
if (imgSize.hasOwnProperty(tagName)){
return imgSize[tagName];
} else {
return [600, 350];
}
}
.hasOwnProperty处报错,error Do not access Object.prototype method 'hasOwnProperty' from target object no-prototype-builtins。所以我进行了修改。
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 = (tempDocxPath, wordData, fileName, imgSize) => {
console.log(wordData);
// 这里要引入处理图片的插件
var ImageModule = require('docxtemplater-image-module-free');
const expressions = require("angular-expressions");
// 读取并获得模板文件的二进制内容
JSZipUtils.getBinaryContent(tempDocxPath, function (error, content) {
if (error) {
throw error;
}
expressions.filters.size = function (input, width, height) {
return {
data: input,
size: [width, height],
};
};
// function angularParser (tag) {
// const expr = expressions.compile(tag.replace(/’/g, "'"));
// return {
// get (scope) {
// return expr(scope);
// },
// };
// }
// 图片处理
let opts = {}
opts = {
// 图像是否居中
centered: false
};
opts.getImage = (chartId) => {
// console.log(chartId);//base64数据
// 将base64的数据转为ArrayBuffer
return base64DataURLToArrayBuffer(chartId);
}
opts.getSize = function (img, tagValue, tagName) {
// console.log(img);//ArrayBuffer数据
// console.log(tagValue);//base64数据
// console.log(tagName);//wordData对象的图像属性名
// 自定义指定图像大小
if (imgSize.hasOwnProperty(tagName)){
return imgSize[tagName];
} else {
return [600, 350];
}
}
// opts.getSize = function (img, tagValue, tagName) {
// // console.log(img);//ArrayBuffer数据
// // console.log(tagValue);//base64数据
// // console.log(tagName);//wordData对象的图像属性名
// // 自定义指定图像大小
// if (imgSize.hasOwnProperty.call(imgSize, 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);
});
}
第三步创建页面调用组件。先点击图片转换,再点击图片插入WORD。
<template>
<div>
<el-button @click="toTo('/static/img/1.png')">图片转换</el-button>
<el-button @click="exportWordFile()">图片插入WORD</el-button>
</div>
</template>
<script>
import { imageToBase64 } from '@/tobase64'; // 假设 imageHelper.js 的路径是这个
import {exportWord} from '@/exportword'
export default {
name: 'ExportFile',
data () {
return {
form: {},
};
},
methods: {
toTo(imagePath1){
imageToBase64(imagePath1)
.then(base64Data => {
this.form.imgUrl=base64Data;
console.log(base64Data); // 在这里你可以对 base64 数据进行处理或使用
return base64Data;
})
.catch(error => {
console.error('Error converting image to base64:', error);
});
},
exportWordFile (){
// this.form.imgUrl=this.toTo('/static/img/1.png');
// console.log(this.form.imgUrl);
let imgSize = {
imgUrl:[65, 65], //控制导出的word图片大小
};
exportWord("/PUR-OE-RNPL-RCS-model.docx", this.form, "demo.docx", imgSize);
//参数1:模板文档
//参数2:字段参数
//参数3:输出文档
//参数4:图片大小C:\Users\9431\Desktop\vue\vue-project\project\public\PUR-OE-RNPL-RCS-model.docx
}
},
};
</script>
模板WORD
插入并导出后