docxtemplater库实现前端截图并将图片插入到word文档中(纯前端js代码) ...

打印 上一主题 下一主题

主题 1874|帖子 1874|积分 5622

目录
一、必要引入的包
二、详细实现代码
1、主程序代码
(1)函数的定义和参数:
(2)使用htmlcanvas截图:
(3)获取图片的 Base64数据和Blob:
(4)加载Word模板:
(5)解压模板文件:
(6)设置图片模板:
(7)渲染模板:
(8)生成并下载Word文件:
(9)错误处理:
2、干系函数代码
(1)正则表达式定义:
(2)函数主体:
(3)数据解析:
三、存在的一些问题(还能在继续优化)

浅记录一下~~~~~有错误的地方渴望大家可以指正,共同进步呀!

一、必要引入的包

  1. import html2canvas from 'html2canvas';
  2. import { saveAs } from 'file-saver';
  3. import PizZip from 'pizzip';
  4. import Docxtemplater from 'docxtemplater';
  5. import ImageModule from 'docxtemplater-image-module-free';
复制代码


  • html2canvas: 是一个将 HTML 元素截图并转换为图像的 JavaScript 库。其焦点功能是将指定的HTML元素渲染为一个可用于下载或展示的图像(通常为PNG格式)。当必要将网页中的某些部分以图像情势生存或展示时使用。使用 canvas 技能来绘制和导出图像。支持自定义分辨率和图像格式。适用于前端项目,无需依赖服务器。支持大多数 HTML 和 CSS 特性。能够处理动态内容。
  • saveAs:saveAs是一个函数,专门用于在欣赏器中生存文件。它允许用户通过前端生成或处理的文件,在客户端直打仗发下载。焦点功能是提供文件下载功能,解决差别欣赏器对文件下载操纵的兼容性问题。file-saver可以用来生存 Blob 文件:当前端生成了二进制文件(Blob),必要触发文件下载时使用;支持多种格式的文件下载:可以下载文本、图片、音频、视频等多种格式的文件;可跨欣赏器兼容性:解决了差别欣赏器(如 Chrome、Firefox、IE 等)对文件下载操纵的兼容问题。
  • pizzip:PizZip是一个JavaScript库,用于处理ZIP文件(读取、解压、操纵和重新压缩)。焦点功能:解压和读取ZIP文件内容;创建和修改ZIP文件;与其他工具(如docxtemplater)联合,操纵基于ZIP格式的文档(如DOCX、PPTX)。
  • docxtemplater:Docxtemplater 是一个 JavaScript 库,用于操纵 Microsoft Word 文档(DOCX 文件),通过模板引擎替换变量或动态生成内容。焦点功能:模板化文档生成:通过在 DOCX 模板文件中设置占位符(如 {name}),联合数据填充功能生成个性化文档。文档内容替换:动态修改 Word 文档中的文本、表格、图片等内容。与 ZIP 文件操纵库联合:与 PizZip 搭配使用,解压和操纵 DOCX 文件(DOCX 本质上是一个 ZIP 包含多种文件)。
  • ImageModule:在使用 docxtemplater 库处理 Word 文档模板时,ImageModule是一个附加模块,它是 docxtemplater-image-module-free 提供的一个功能模块,用于在生成的 Word 文档中插入图片。这是一个 "插件" 式的功能扩展。通过 ImageModule,你可以指定图片的泉源(如 Base64 编码、URL、文件路径等)以及图片的大小和布局。原始的 docxtemplater 库只支持文本的动态填充。假如必要插入图片,就必要额外安装并设置 ImageModule。docxtemplater-image-module-free 这是一个 npm 包的名称,它是 docxtemplater 的一个插件模块。焦点功能允许将图片动态插入到 Word 模板中。适用配合 docxtemplater 使用,基于模板生成包含图片的 Word 文档。

二、详细实现代码

1、主程序代码

  1. export async function ScreenShot(elID: string) {
  2.     const element = document.getElementById(elID);
  3.     if (!element) {
  4.         console.error('Element not found!');
  5.         return;
  6.     }
  7.     try {
  8.         // 使用 html2canvas 截取元素并生成 Canvas
  9.         const canvas = await html2canvas(element, {
  10.             useCORS: true,
  11.             scale: window.devicePixelRatio < 3 ? window.devicePixelRatio : 2,
  12.             allowTaint: true,
  13.         });
  14.         // 将 Canvas 转换为 Base64 图片
  15.         const imageBase64 = canvas.toDataURL('image/png');
  16.         const imageblob = canvas.toBlob(function () { }, 'image/png')
  17.         // 加载 Word 模板文件
  18.         const response = await fetch('/template.docx'); // 模板路径
  19.         const arrayBuffer = await response.arrayBuffer();
  20.         // 使用 PizZip 解压模板
  21.         const zip = new PizZip(arrayBuffer);
  22.         const imageOptions = {
  23.             getImage(tagValue: any) {
  24.                 return base64Parser(tagValue);
  25.             },
  26.             getSize(img: any, tagValue: any, tagName: any, context: any) {
  27.                 return [400, 240];
  28.             },
  29.             centered: true,
  30.         };
  31.         const doc = new Docxtemplater(zip, {
  32.             modules: [new ImageModule(imageOptions)],
  33.         });
  34.         // 渲染模板
  35.         doc.render({
  36.             image: imageBase64, // 仅保留 Base64 数据部分
  37.         });
  38.         // 生成 Word 文件并下载
  39.         const out = doc.getZip().generate({
  40.             type: 'blob',
  41.             mimeType:
  42.                 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
  43.         });
  44.         saveAs(out, 'screenshot.docx');
  45.     } catch (error) {
  46.         console.error('Error generating Word document:', error);
  47.     }
  48. }
复制代码
这段代码实现了一个截图功能,将 HTML 页面中的某个元素(由 elID 指定)截图并生存到Word文档中。详细步调包括:

  • 使用 html2canvas 将指定 HTML 元素转换为图片。
  • 加载Word模板文件(template.docx)。
  • 使用 docxtemplater 和 docxtemplater-image-module-free 插件将图片插入 Word 文档模板中。生成新的 Word 文件,并允许用户下载。
接下来进行拆解主程序代码,详细阐明每一段代码实现的意义:
(1)函数的定义和参数:

定义一个异步函数ScreenShot,接受一个参数elID(要截图的HTML元素的 ID)。首先通过document.getElementById获取指定的DOM元素。假如找不到目的元素,打印错误并停止函数。
  1. export async function ScreenShot(elID: string) {
  2.     const element = document.getElementById(elID);
  3.     if (!element) {
  4.         console.error('Element not found!');
  5.         return;
  6.     }
复制代码
(2)使用htmlcanvas截图:

html2canvas将 HTML 元素渲染为 Canvas 图像。useCORS: true:启用跨域支持,允许加载跨域的图片资源。scale: window.devicePixelRatio < 3 ? window.devicePixelRatio : 2:根据装备像素比调整图像分辨率,限制最大缩放比为2。allowTaint: true:允许跨域图片资源渲染到 Canvas(潜伏安全问题)。输出一个Canvas 对象包含 HTML 元素的渲染结果。
  1. const canvas = await html2canvas(element, {
  2.     useCORS: true,
  3.     scale: window.devicePixelRatio < 3 ? window.devicePixelRatio : 2,
  4.     allowTaint: true,
  5. });
复制代码
(3)获取图片的 Base64数据和Blob:

toDataURL:将 Canvas 转换为 Base64 编码的 PNG 图片。用于将图片数据以文本情势嵌入到 Word 文档。toBlob:将 Canvas 转换为二进制 Blob 对象。可以用作图片文件生存或进一步操纵。
  1. const imageBase64 = canvas.toDataURL('image/png');
  2. const imageblob = canvas.toBlob(function () { }, 'image/png');
复制代码
(4)加载Word模板:

通过 fetch 哀求加载 Word 模板文件。.docx 是 Word 文档的文件格式,本质上是一个 ZIP 文件。将相应转换为 arrayBuffer(字节数组),用于后续操纵。(这里的template.docx是本身预先创建的文档,必要将该文档放在public根目录下,文档里必要写入图片的占位符{%image})
  1. const response = await fetch('/template.docx');
  2. const arrayBuffer = await response.arrayBuffer();
复制代码

(5)解压模板文件:

 PizZip 是一个 ZIP 文件处理库,用于解压和操纵 Word 模板。arrayBuffer 是模板文件的字节内容。解压后的 ZIP 文件布局,供 Docxtemplater 使用。
  1. const zip = new PizZip(arrayBuffer);
复制代码
(6)设置图片模板:

getImage:定义如何解析模板中的图片占位符数据。调用 base64Parser(自定义函数,后续会提到)解析 Base64 数据。getSize:定义图片尺寸。这里固定为宽 400px,高 240px。centered:指定图片在 Word 文档中的对齐方式,设置为居中。
  1. const imageOptions = {
  2.     getImage(tagValue: any) {
  3.         return base64Parser(tagValue);
  4.     },
  5.     getSize(img: any, tagValue: any, tagName: any, context: any) {
  6.         return [400, 240];
  7.     },
  8.     centered: true,
  9. };
复制代码
(7)渲染模板:

Docxtemplater 是一个模板引擎,用于动态填充 Word 文档。ImageModule 插件支持插入图片到 Word 模板。将 imageBase64(截图的 Base64 数据)绑定到模板中的图片占位符。
  1. const doc = new Docxtemplater(zip, {
  2.     modules: [new ImageModule(imageOptions)],
  3. });
  4. doc.render({
  5.     image: imageBase64,
  6. });
复制代码
(8)生成并下载Word文件:

 type: 'blob':指定输出文件范例为二进制 Blob。mimeType:指定文件为 Word 文档(docx 格式)。使用 file-saver 库的 saveAs 方法将生成的 Word 文件提供给用户下载,文件名为 screenshot.docx。
  1. const out = doc.getZip().generate({
  2.     type: 'blob',
  3.     mimeType:
  4.         'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
  5. });
  6. saveAs(out, 'screenshot.docx');
复制代码
(9)错误处理:

捕获并处理任何可能在截图、模板渲染或文件生成过程中发生的错误。保障代码在异常情况下不会瓦解,并提供调试信息。
  1. catch (error) {
  2.     console.error('Error generating Word document:', error);
  3. }
复制代码


2、干系函数代码

  1. const base64Regex =
  2.     /^(?:data:)?image\/(png|jpg|jpeg|svg|svg\+xml);base64,/;
  3. const validBase64 =
  4.     /^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$/;
  5. function base64Parser(tagValue: any) {
  6.     if (
  7.         typeof tagValue !== "string" ||
  8.         !base64Regex.test(tagValue)
  9.     ) {
  10.         return false;
  11.     }
  12.     const stringBase64 = tagValue.replace(base64Regex, "");
  13.     if (!validBase64.test(stringBase64)) {
  14.         throw new Error(
  15.             "Error parsing base64 data, your data contains invalid characters"
  16.         );
  17.     }
  18.     // For nodejs, return a Buffer
  19.     if (typeof Buffer !== "undefined" && Buffer.from) {
  20.         return Buffer.from(stringBase64, "base64");
  21.     }
  22.     // For browsers, return a string (of binary content) :
  23.     const binaryString = window.atob(stringBase64);
  24.     const len = binaryString.length;
  25.     const bytes = new Uint8Array(len);
  26.     for (let i = 0; i < len; i++) {
  27.         const ascii = binaryString.charCodeAt(i);
  28.         bytes[i] = ascii;
  29.     }
  30.     return bytes.buffer;
  31. }
复制代码

这段代码定义了一个函数 base64Parser,用于解析和验证 Base64 格式的图片数据。
它主要完成以下任务:
1、查抄输入数据是否是有用的 Base64 图片数据。
2、解析并将 Base64 数据转换为适合运行环境的格式:
(1)在 Node.js 环境下,返回 Buffer 对象。
(2)在欣赏器环境下,返回 ArrayBuffer(二进制内容)。
下面将对干系函数代码进行渐渐解析,以便读者明确。

(1)正则表达式定义:

base64Regex: 匹配 Base64 图片数据的前缀部分,确保数据格式正确。布局解析:(?:data?:可选的 data: 前缀。image\/(png|jpg|jpeg|svg|svg\+xml):匹配常见的图片 MIME 范例,包括 png、jpg、jpeg 和 svg。;base64,:固定部分,表现后续内容是 Base64 编码数据。
  1. const base64Regex =
  2.     /^(?:data:)?image\/(png|jpg|jpeg|svg|svg\+xml);base64,/;
复制代码
validBase64:  匹配纯 Base64 数据(即编码内容部分)。[A-Za-z0-9+/]{4}:每组 4 个字符,由字母、数字和 + 或 / 组成。末端部分允许补齐字符:{2}==:2 个有用字符,后跟 2 个 =。{3}=:3 个有用字符,后跟 1 个 =。
  1. const validBase64 =
  2.     /^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$/;
复制代码
(2)函数主体:

(a)验证输入数据是否为字符串,而且符合 Base64 图片数据的格式。条件 1:tagValue 必须是字符串。条件 2:tagValue 必须匹配 base64Regex。假如不符合上述条件,返回 false,表现数据无效。
  1. function base64Parser(tagValue: any) {
  2.     if (
  3.         typeof tagValue !== "string" ||
  4.         !base64Regex.test(tagValue)
  5.     ) {
  6.         return false;
  7.     }
复制代码
(b)将 Base64 数据的前缀部分移除,仅保存纯 Base64 编码内容。
示例:
输入:data:image/png;base64,ABC123...
输出:ABC123...
  1. const stringBase64 = tagValue.replace(base64Regex, "");
复制代码
(c)查抄提取的base64数据是否有用格式,使用validbase64正则表达式验证纯base64数据。假如不匹配,抛堕落误,提示数据包含无效字符。
  1. if (!validBase64.test(stringBase64)) {
  2.     throw new Error(
  3.         "Error parsing base64 data, your data contains invalid characters"
  4.     );
  5. }
复制代码
(3)数据解析:

 (a)在node.js的环境下,将base64数据解析为Buffer,仅当全局buffer对象存在,而且支持Buffer.from方法时执行,Buffer对象,适合在服务器端处理二进制数据。
  1. if (typeof Buffer !== "undefined" && Buffer.from) {
  2.     return Buffer.from(stringBase64, "base64");
  3. }
复制代码
(b)在欣赏器环境下,将base64数据解析为ArrayBuffer。使用window.atob解码八涩数据为二进制字符串。创建Unit8Array,逐字节填充二进制数据。binaryString.charCodeAt(i): 获取字符的ASCII码值。返回Unit8Array.buffer,即ArrayBuffer对象。 
  1. const binaryString = window.atob(stringBase64);
  2. const len = binaryString.length;
  3. const bytes = new Uint8Array(len);
  4. for (let i = 0; i < len; i++) {
  5.     const ascii = binaryString.charCodeAt(i);
  6.     bytes[i] = ascii;
  7. }
  8. return bytes.buffer;
复制代码
三、存在的一些问题(还能在继续优化)



  • 图片尺寸调整:动态盘算图片尺寸以适配模板占位符。
  • 错误提示友爱化:在 UI 层提示用户错误信息,而非仅打印到控制台。
  • 模板路径动态化:允许用户选择模板文件,而非硬编码路径。
  • 错误提示优化:假如 base64Regex 不匹配,明确指特别式问题。提供示例阐明正确的 Base64 图片数据格式。
  • 性能提升:在欣赏器环境下,考虑使用更高效的 TextDecoder 替换 window.atob。
  • 兼容性加强:假如目的环境是欣赏器,考虑移除 Node.js 部分的代码,减少代码体积。
四、完整代码
  1. import html2canvas from 'html2canvas';
  2. import { saveAs } from 'file-saver';
  3. import PizZip from 'pizzip';
  4. import Docxtemplater from 'docxtemplater';
  5. import ImageModule from 'docxtemplater-image-module-free';export async function ScreenShot(elID: string) {
  6.     const element = document.getElementById(elID);
  7.     if (!element) {
  8.         console.error('Element not found!');
  9.         return;
  10.     }
  11.     try {
  12.         // 使用 html2canvas 截取元素并生成 Canvas
  13.         const canvas = await html2canvas(element, {
  14.             useCORS: true,
  15.             scale: window.devicePixelRatio < 3 ? window.devicePixelRatio : 2,
  16.             allowTaint: true,
  17.         });
  18.         // 将 Canvas 转换为 Base64 图片
  19.         const imageBase64 = canvas.toDataURL('image/png');
  20.         const imageblob = canvas.toBlob(function () { }, 'image/png')
  21.         // 加载 Word 模板文件
  22.         const response = await fetch('/template.docx'); // 模板路径
  23.         const arrayBuffer = await response.arrayBuffer();
  24.         // 使用 PizZip 解压模板
  25.         const zip = new PizZip(arrayBuffer);
  26.         const imageOptions = {
  27.             getImage(tagValue: any) {
  28.                 return base64Parser(tagValue);
  29.             },
  30.             getSize(img: any, tagValue: any, tagName: any, context: any) {
  31.                 return [400, 240];
  32.             },
  33.             centered: true,
  34.         };
  35.         const doc = new Docxtemplater(zip, {
  36.             modules: [new ImageModule(imageOptions)],
  37.         });
  38.         // 渲染模板
  39.         doc.render({
  40.             image: imageBase64, // 仅保留 Base64 数据部分
  41.         });
  42.         // 生成 Word 文件并下载
  43.         const out = doc.getZip().generate({
  44.             type: 'blob',
  45.             mimeType:
  46.                 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
  47.         });
  48.         saveAs(out, 'screenshot.docx');
  49.     } catch (error) {
  50.         console.error('Error generating Word document:', error);
  51.     }
  52. }const base64Regex =
  53.     /^(?:data:)?image\/(png|jpg|jpeg|svg|svg\+xml);base64,/;
  54. const validBase64 =
  55.     /^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$/;
  56. function base64Parser(tagValue: any) {
  57.     if (
  58.         typeof tagValue !== "string" ||
  59.         !base64Regex.test(tagValue)
  60.     ) {
  61.         return false;
  62.     }
  63.     const stringBase64 = tagValue.replace(base64Regex, "");
  64.     if (!validBase64.test(stringBase64)) {
  65.         throw new Error(
  66.             "Error parsing base64 data, your data contains invalid characters"
  67.         );
  68.     }
  69.     // For nodejs, return a Buffer
  70.     if (typeof Buffer !== "undefined" && Buffer.from) {
  71.         return Buffer.from(stringBase64, "base64");
  72.     }
  73.     // For browsers, return a string (of binary content) :
  74.     const binaryString = window.atob(stringBase64);
  75.     const len = binaryString.length;
  76.     const bytes = new Uint8Array(len);
  77.     for (let i = 0; i < len; i++) {
  78.         const ascii = binaryString.charCodeAt(i);
  79.         bytes[i] = ascii;
  80.     }
  81.     return bytes.buffer;
  82. }
复制代码
参考网址:Image module | docxtemplater


免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

怀念夏天

论坛元老
这个人很懒什么都没写!
快速回复 返回顶部 返回列表