前端 word 导出
前端的常规导出,一般是 excel,下载图片什么。word 的导出有点不太一样。
导出前的准备,安装相关依赖
import Docxtemplater from 'docxtemplater'
import PizZip from 'pizzip'
import PizZipUtils from 'pizzip/utils/index.js'
import { saveAs } from 'file-saver'
import ImageModule from 'docxtemplater-image-module-free'
要新新建一个 word 的文件,中间的值用 {} ,类似于 tsx 或者 jsx 的写法,和 src 平级新建一个名称为 public 的文件夹

index.docx 的内容

第一个箭头,是常规的对象赋值,第二个,是表格循环,第三个是图片的显示
export const exportWord = ({ templateName = 'index.docx', docData = {}, fileName = '', fileType = 'docx' }: any) => {
const base64DataURLToArrayBuffer = (dataURL: any) => {
const base64Regex = /^data:image\/(png|jpg|jpeg|svg|svg\+xml);base64,/
const stringBase64 = dataURL.replace(base64Regex, '')
let binaryString
if (typeof window !== 'undefined') {
binaryString = window.atob(stringBase64)
} else {
binaryString = Buffer.from(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
}
const getBase64 = (img: any) => {
function getBase64Image({ image, width, height }: any) {
const canvas = document.createElement('canvas')
canvas.width = width || image.width
canvas.height = height || image.height
const ctx: any = canvas.getContext('2d')
ctx.drawImage(image, 0, 0, canvas.width, canvas.height)
var dataURL = canvas.toDataURL()
return dataURL
}
var image = new Image()
image.crossOrigin = ''
image.src = img
return new Promise((resolve, reject) => {
image.onload = function () {
resolve(getBase64Image({ image }))
}
})
}
loadFile(`/${templateName}`, function (error: any, content: any) {
if (error) {
throw error
}
const imageOpts = {
getImage: async (tagValue: any, tagName: any) => {
const base64Regex = /^data:image\/(png|jpg|jpeg|svg|svg\+xml);base64,/
let newValue: any = ''
if (base64Regex.test(tagValue)) {
newValue = base64DataURLToArrayBuffer(tagValue)
} else if (tagValue.includes('http')) {
await getBase64(tagValue).then((data) => {
newValue = base64DataURLToArrayBuffer(data)
})
} else {
await PizZipUtils.getBinaryContent(tagValue, function (error, content) {
if (!error) {
newValue = content
}
})
}
return newValue
},
getSize: function (img: any, tagValue: any, tagName: any) {
return [150, 150]
}
}
const imageModule = new ImageModule(imageOpts)
const zip = new PizZip(content)
const doc = new Docxtemplater()
.loadZip(zip)
.setOptions({
paragraphLoop: true,
linebreaks: true,
nullGetter: nullGetter as any
})
.attachModule(imageModule)
.compile()
doc.renderAsync(docData).then(function () {
const out = doc.getZip().generate({
type: 'blob',
mimeType: 'application/vnd.openxmlformats-officedocument.wordprocessingml.document'
})
saveAs(out, `${fileName || new Date().getTime()}.${fileType}`)
})
})
}
图片的导出,如果是本地的话,填写正确的引入地址,也以直接导出 base64 格式的图片,网络图片,也是需要先转换成 bas464,再导出。网络图片导出有一个小坑,就是跨域问题。一般是用 jq 的一个方法,具体可以再查一下。

浙公网安备 33010602011771号