docxtemplater避坑!!! 前端导出word怎么插入本地图片或base64 有完整示例

前端 0

docxtemplater库实现前端通过模板导出word,遇到需求,要插图片并转成word并导出,在图片转换这块遇到了问题,网上查示例大多都跑不通,自己琢磨半天,总算搞明白了。

附上清晰完整示例,供参考。

如有不懂,私我询问!

首先需要一个word文件作为模板test.docx

必须是docx文件!!!

{%} 代表图片 xgq是变量

安装需要的包

npm install docxtemplaternpm install docxtemplater-image-module-freenpm install pizzipnpm install file-savernpm install html2canvas # 如需截图的话 安装
import Docxtemplater from 'docxtemplater';import { saveAs } from 'file-saver';import PizZip from 'pizzip';import ImageModule from 'docxtemplater-image-module-free';import html2canvas from 'html2canvas';import image from './20240522152640.jpg';import docx from './test.docx';

插入本地图片并转换

const imageData = await fetch(image);const imageArrayBuffer = await imageData.arrayBuffer();const imgDataDict: Record<string, ArrayBuffer> = {  xgq: imageArrayBuffer,};const docxData = await fetch(docx);const docxArrayBuffer = await docxData.arrayBuffer();const zip = new PizZip(docxArrayBuffer);const doc = new Docxtemplater(zip, {  paragraphLoop: true,  linebreaks: true,  modules: [    new ImageModule({      getImage: (value: string, key: string) => {        return imgDataDict[key];      },      getSize: (afterValue: ArrayBuffer, value: string, key: string) => {        return [400, 400];      },    }),  ],});doc.render({  xgq: "xgq", // 这里得是字符串否则会报错});const blob = doc.getZip().generate({  type: "blob",  mimeType:    "application/vnd.openxmlformats-officedocument.wordprocessingml.document",});saveAs(blob, "download.docx");

插入base64图片并转换

const base64 =  "data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAASABIAAD/4QBARXhpZgAATU0AKgAAAAgAAYdpAAQAAAABAAAAGgAAAAAAAqACAAQAAAABAAAAzKADAAQAAAABAAAAvAAAAAD/4gIQSUNDX1BST0ZJTEUAAQEAAAIAYXBwbAQAAABtbnRyUkdCIFhZWiAH6AAFABYADQABACJhY3NwQVBQTAAAAABBUFBMAAAAAAAAAAAAAAAAAAAAAAAA9tYAAQAAAADTLWFwcGyUGWuT9Z12r6yIp8KqjC97AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAApkZXNjAAAA/AAAACZjcHJ0AAABJAAAAFB3dHB0AAABdAAAABRyWFlaAAABiAAAABRnWFlaAAABnAAAABRiWFlaAAABsAAAABRyVFJDAAABxAAAABBjaGFkAAAB1AAAACxiVFJDAAABxAAAABBnVFJDAAABxAAAABBtbHVjAAAAAAAAAAEAAAAMZW5VUwAAAAoAAAAcADIAMgBCADIAVwAAbWx1YwAAAAAAAAABAAAADGVuVVMAAAA0AAAAHABDAG8AcAB5AHIAaQBnAGgAdAAgAEEAcABwAGwAZQAgAEkAbgBjAC4ALAAgADIAMAAyADRYWVogAAAAAAAA9tYAAQAAAADTLVhZWiAAAAAAAABqxAAANdEAAAD6WFlaIAAAAAAAAGVxAAC4owAAEUdYWVogAAAAAAAAJqAAABGMAADA63BhcmEAAAAAAAAAAAAB9gRzZjMyAAAAAAABC7cAAAWW///zVwAABykAAP3X///7taYAAAPaAADA9v/AABEIALwAzAMBIgACEQEDEQH/xAAfAAABBQEBAQEBAQAAAAAAAAAAAQIDBAUGBwgJCgv/xAC1EAACAQMDAgQDBQUEBAAAAX0BAgMABBEFEiExQQYTUWEHInEUMoGRoQgjQrHBFVLR8CQzYnKCCQoWFxgZGiUmJygpKjQ1Njc4OTpDREVGR0hJSlNUVVZXWFlaY2RlZmdoaWpzdHV2d3h5eoOEhYaHiImKkpOUlZaXmJmaoqOkpaanqKmqsrO0tba3uLm6wsPExcbHyMnK0tPU1dbX2Nna4eLj5OXm5+jp6vHy8/T19vf4+fr/xAAfAQADAQEBAQEBAQEBAAAAAAAAAQIDBAUGBwgJCgv/xAC1EQACAQIEBAMEBwUEBAABAncAAQIDEQQFITEGEkFRB2FxEyIygQgUQpGhscEJIzNS8BVictEKFiQ04SXxFxgZGiYnKCkqNTY3ODk6Q0RFRkdISUpTVFVWV1hZWmNkZWZnaGlqc3R1dnd4eXqCg4SFhoeIiYqSk5SVlpeYmZqio6Slpqeoqaqys7S1tre4ubrCw8TFxsfIycrS09TV1tfY2dri4+Tl5ufo6ery8/T19vf4+fr/2wBDAAICAgICAgMCAgMFAwMDBQYFBQUFBggGBgYGBggKCAgICAgICgoKCgoKCgoMDAwMDAwODg4ODg8PDw8PDw8PDw//2wBDAQICAgQEBAcEBAcQCwkLEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBD/3QAEAA3/2gAMAwEAAhEDEQA/APGUOepqT8ag4FSK6gAV9hY/hv2CHYNGDTgQDTtwosY/VyLBpjLxwKs9qj4osHsCuB60pAqVhnpUZ44q0hqFtCJck81Jhaa/IqKnYLeRYzxwaRXIPNQjrT+P8itIRE6XNuWPNqVWJwapcVMrKMU2H1dGghJbDHIqcbR0wKzw/PJqQOprLlH7KxoA9KmVjnrVJJFwBUyYByamSM6sLl5DkcmrA6cGqKMO1WVYbRVKOmxl7LzJ8570nTvio1cE1IDmiwuS4nHrTWBxUlMJyKFEidFdytJkEUzJqSQcjFRU+Qnktof/0PEFfHWpQ4NZ8cgYHJqyrDjmvtOQ/jCVJX2LysScYp9VVkGanVg1PlZnKiiYdKaVx3pM0Zz3qDKVG3QPxqBvvGp6gbqatRuHsRpGe9MK04njim1agwVLyEwKWmEmjJrWMC40Ux9PAHWolp+TSlHUTpLsTbvanKc1XXr1qTJHSh02hexXYtqcYq0r7jiqCngc1KGwcg4rNxZEqBohivSplYkCs5HYnk1aD8dauKM3SRcRuamEmKoK3PJqYFT1Na+yREqStsXN4IpjHAzUGRSsxx1odK2xn7JA7Emo+tBPqaTI9aPZsPYo/9H54Uiplc8VVi5BzUwZRX3fKfyPKhqaSyLjFSK5HSqKuQc1ZSQHOaEiJULFsSHFOWTB5qAMuKUHJpSimZOi2TM4PSm5FN/Cj8KaiL6uxKQjNLRW/Ig9gR9KKU9aSmlYmVBhRRRScUL2TFBwafnNR09elUZ2ZICOKn3CqtA45BpOKFysvKRipQwGKzg7CpllOAKXIifZs0El55p/melUhIBTg4Na2JlSdjTWVdozS+atUARjrRk0mYuhcuM4J4pKqZNPEpAxQmhcttD/0vm4E9jip1wQMmqox3pwx6V+hn8tSo6l0ZqVCADmqwZWOBmnYAo0E8OXQx4xU+/bzms0N2qxvT3osZSw5cWUmnbz61VjdOetSb096diPYk273o3e9Q7096N6e9AvZeZLmiot6e9PFBEqXmOopM0ZoJ9kLTh0pm4UbhQYexQ4tz1pQc0zf7UZPagFQuS0uSKh3EUbzVofsETb/anq/HpVfLUm5h7VcVqHskXRJ71J5tZ+9vWpN3vV8rInQRc870pPPqpvoyKlxZzSoan/0/mqlyaKK/ROU/mlw8iVSVORUqsW61DS5I6UKInBtE9OBzTVK7Rk80/8KdjF02iRWKjgZp28+lRc04dKfKO2mxYyKTg1BvPrRuPrRymXsr6EhbB+lO86q+c96T8TSasEqCRbEuetL5oqkTjvSbj60iPZIviXPQU9WLdqzg+DnNSCYjoTTRj7JF/n0pu81T85z60eZ7mqSIlDsWi5z0pPMPpVUyGmbmz3xVWIcGXDLgUwz1V3Gkznrit4xaZo4roWfObNHnVWyaXd9K0J5O5ZEuepp/nVS8zFHm0B7NH/1PmrI9aUfWoiw7Uoc8cV+iu60P555UT4oxSbjRu9aZlccBzVyqYPepfNb0FOwmT5xSZFV2lb0pBKcjinYXKWPmowTTqO9JkOCGYI5pu9Ka0hBIqDkVLdyeVEzOD90U3cai3Gl3Gmokuj1H+YR2o8wmombjmmFhT5UR7NdC2JccU/etUNwp29a0hFGcqTLodaXzFqjvFOBzzV8iGqK6lppMjio97VFk0u41omV7KJP5ny4qDcaYXNN3etWooiVNIl3Gjcaj3rTDLzT5ETyo//1fl+pVIwKhyKWv1DlP595WWNw9aM5qvT1YClyoXKTZPrT93vUG8UoYE4o0FYsAg9TSgDqKgpcn1rOS1CxY3n+9RuPrUO4UbhS5GKxIeeajyKTce1Nq4q24WQ4n0phb3pCwFQsc5NWojsKWJ6nNRk+9NJwM1ExB6U+Uz9kTZ96XJqtT9x9acURKjcnB9aeGI71U3Gnhx3rRRZDpFlZTnrTxLVUMDS5FVYSplouCM5qHdnqaiyKXIppA6ViTIqM9aMim7hSsHskf/W+W6UEgYqvk+tGT61+vch+C2LO40m41XyfWjJ9aTponlLY5FKDg5qpub1p4kyeah0kQ4FreaN5qvvApd59KXs12F7MuUVVEjE0/fjqalwYuQnprHAzUW/3phcEfe/WocQ5R5JPWoyx5pM56GoWJyeaaiP2YFiRio2bbTulROQTxW6p9x8obz6U0uVGRTSR61CSe5p+zQ+Um89vQU8SEiquRTtx6VaQciLG/bzUiSBhVHdnqaN2OhrV0kh8qNHcvqaNy+prP3H1o3H1rNoXIjQznpTCuapiRh0NHmN61k4Gbgrn//X+VOKOKVgB0ptftXLI/BxeKSimMxHSk4NgPpm8U3eaZUqkwsTbxThIemKhWnVXIBNuNG41Dvb0o3t6Vk4MTRLuNJUe9vSje3pS9mxchJv28UzzATUMjtkcVHvb0pezY+UsswIwKiLAdaj3mmkk9afKHKBwTmkIOKKUnNXGCYWGAGnZOMUxmIOKbvNaJJaByjsGkJx1qIyEDtTC5PpQ2mRyyJ9wpS4xVbcfWjLetZTSDkkWBIooLgmod3qaN3vWbSD2bP/0PldwTjimYPpVx16VEeK/dvZo/ByvUUlTlSBmomUml7MCEdOaax44NPb5etQ/L6VMqQWE3H1NLub1NJx9KTioatoBLuPrTGY5603IpjNg1m1cCTzCKTzM8ZqItxUIJ7VPswLec9TTCeetQZf1pM88mlyAWsr6/rRlfX9arb1o3CmCRZyvr+tGR61X3Ck3rQmNokcjNM3DGMUwsDTd4pMaix1MOM0jOMUwkHpQPlY4kDmo/NPrTS45FRUcoKLJvNNHmGoCcUbzRymyp6H/9H5mZAagZRk1pTKOMDFVyq+lf0L7Ndj8FTM9/u1DVtl46UzaPSo5V2KKbRhutVmUAZq8wwSKjdRjpUOPZAUxjvQQtT7P9mo2U5PFYyhqMrsQBkUzOalZQwxUTLs461MqfYBKaRjkU75vSmnOOlR7NhYYz4PNM3A0/6imkGq9mWoDNxpwbjkUc+lFZKn3KjC2ou72pm406iqdLsOUbjdxxTetPyKaTWMqeppFWRHkmk3EUu40xjk1KQ2ITk5pm40jH0pj8CqSBRB3INM3mmZzRT5SuU//9L51mPaq2KsS9RUOBX9JyjqfgyK7KcVCQR1q03SoJOorP2Yyq0bFiajKkDNWqiIyMUcqAgqMoSc1MwA6U2sZLUCn5bUxk9avkZGKjMYPc1j7PsNFEqQOKhAY1bbhitDIoHFDTLXmUmU55puPappOCMUDlaVmPmfQgIJpu01KRim1nJaBGd2R0hGak2ikIxWfKaXItppKkppArKUNSkQlc9DTSpFTYFIVBrHkL5SpTX6VKygE1GRkYrSEUawiiH8aPxpWAHSm1fIi+RH/9k=";const imageArrayBuffer = base64DataURLToArrayBuffer(base64);const imgDataDict: Record<string, ArrayBuffer> = {  xgq: imageArrayBuffer,};const docxData = await fetch(docx);const docxArrayBuffer = await docxData.arrayBuffer();const zip = new PizZip(docxArrayBuffer);const doc = new Docxtemplater(zip, {  paragraphLoop: true,  linebreaks: true,  modules: [    new ImageModule({      getImage: (value: string, key: string) => {        return imgDataDict[key];      },      getSize: (afterValue: ArrayBuffer, value: string, key: string) => {        return [400, 400];      },    }),  ],});doc.render({  xgq: "xgq", // 这里得是字符串否则会报错});const blob = doc.getZip().generate({  type: "blob",  mimeType:    "application/vnd.openxmlformats-officedocument.wordprocessingml.document",});saveAs(blob, "download.docx");
const base64DataURLToArrayBuffer = (dataURL: string) => {  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;};

截图某个网页区域并插入转换

<div id="test" style={{ border: "1px solid red", width: 300 }}>  <div>截图</div>  <button type="button">666</button>  <br />  <img src={image} /></div>;
const dom: any = document.getElementById("test");const canvas = await html2canvas(dom, {  useCORS: true,  scale: 5,});const imageDataURL = canvas.toDataURL("image/png");const response = await fetch(imageDataURL);const imageArrayBuffer = await response.arrayBuffer();const imgDataDict: Record<string, ArrayBuffer> = {  xgq: imageArrayBuffer,};const docxData = await fetch(docx);const docxArrayBuffer = await docxData.arrayBuffer();const zip = new PizZip(docxArrayBuffer);const doc = new Docxtemplater(zip, {  paragraphLoop: true,  linebreaks: true,  modules: [    new ImageModule({      getImage: (value: string, key: string) => {        return imgDataDict[key];      },      getSize: (afterValue: ArrayBuffer, value: string, key: string) => {        return [400, 400];      },    }),  ],});doc.render({  xgq: "xgq", // 这里得是字符串否则会报错});const blob = doc.getZip().generate({  type: "blob",  mimeType:    "application/vnd.openxmlformats-officedocument.wordprocessingml.document",});saveAs(blob, "download.docx");

也许您对下面的内容还感兴趣: