vue使用docxtemplater导出word
<template>
</template>
<script>
import JSZipUtils from "jszip-utils/dist/jszip-utils.js";
import Docxtemplater from "docxtemplater";
import PizZip from "pizzip";
import { saveAs } from "file-saver";
import ImageModule from "docxtemplater-image-module-free";
function loadFile(url, callback) {
JSZipUtils.getBinaryContent(url, callback);
}
export default {
name: "DocRender",
data() {
return {
imageSize: {},
imageMaxHeight: 0,
imageMaxWidth: 0,
templateLocaton: "",
content: {},
outputname: "output.docx"
};
},
methods: {
export(
imageMaxHeight,
imageMaxWidth,
templateLocaton,
imageArray,
wordArray,
outputname
) {
this.content = Object.assign(imageArray, wordArray);
this.imageMaxHeight = imageMaxHeight;
this.imageMaxWidth = imageMaxWidth;
this.templateLocaton = templateLocaton;
this.outputname = outputname;
this.initializeImageSize(imageArray);
console.log(this.imageSize);
console.log(this.content);
this.renderDoc();
},
initializeImageSize(array) {
let that = this;
Object.keys(array).forEach(async key => {
await this.getImageOriginalSize(array[key]).then(res => {
that.imageSize[key] = [res];
});
});
},
getImageOriginalSize(url) {
var that = this;
return new Promise(function(resolve, reject) {
var image = new Image();
image.src = url;
image.onload = function() {
resolve({ width: image.width, height: image.height });
};
}).then(sizeObj => {
const maxWidth = that.imageMaxWidth;
const maxHeight = that.imageMaxHeight;
const aspectRatio = sizeObj.width / sizeObj.height;
const widthRatio = sizeObj.width / maxWidth;
const heightRatio = sizeObj.height / maxHeight;
if (widthRatio < 1 && heightRatio < 1) {
return [sizeObj.width, sizeObj.height];
}
let finalWidth, finalHeight;
if (widthRatio > heightRatio) {
finalWidth = maxWidth;
finalHeight = sizeObj.height / widthRatio;
} else {
finalHeight = maxHeight;
finalWidth = sizeObj.width / heightRatio;
}
return [Math.round(finalWidth), Math.round(finalHeight)];
});
},
replaceErrors(key, value) {
if (value instanceof Error) {
return Object.getOwnPropertyNames(value).reduce(function(error, key) {
error[key] = value[key];
return error;
}, {});
}
return value;
},
renderDoc() {
var that = this;
console.log(that.templateLocaton);
loadFile(that.templateLocaton, (error, content) => {
if (error) {
throw error;
}
var opts = {};
opts.centered = false;
opts.fileType = "docx";
opts.getImage = function(tagValue, tagName) {
return new Promise(function(resolve, reject) {
JSZipUtils.getBinaryContent(tagValue, function(error, content) {
if (error) {
return reject(error);
}
return resolve(content);
});
});
};
opts.getSize = (img, tagValue, tagName) => {
console.log(that.imageSize[tagName][0]);
return that.imageSize[tagName][0];
};
var imageModule = new ImageModule(opts);
var zip = new PizZip(content);
const doc = new Docxtemplater()
.loadZip(zip)
.attachModule(imageModule)
.compile();
doc.resolveData(that.content).then(() => {
try {
doc.render();
} catch (error) {
console.log(JSON.stringify({ error: error }, that.replaceErrors));
if (error.properties && error.properties.errors instanceof Array) {
const errorMessages = error.properties.errors
.map(function(error) {
return error.properties.explanation;
})
.join("\n");
console.log("errorMessages", errorMessages);
}
throw error;
}
var out = doc.getZip().generate({
type: "blob",
mimeType:
"application/vnd.openxmlformats-officedocument.wordprocessingml.document"
});
saveAs(out, that.outputname);
});
});
}
}
};
</script>
<style scoped>
</style>