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

目录

一、需要引入的包

二、具体实现代码

1、主程序代码

(1)函数的定义和参数:

(2)使用htmlcanvas截图:

(3)获取图片的 Base64数据和Blob:

(4)加载Word模板:

(5)解压模板文件:

(6)配置图片模板:

(7)渲染模板:

(8)生成并下载Word文件:

(9)错误处理:

2、相关函数代码

(1)正则表达式定义:

(2)函数主体:

(3)数据解析:

三、存在的一些问题(还能在继续优化)


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

一、需要引入的包

import html2canvas from 'html2canvas';
import { saveAs } from 'file-saver';
import PizZip from 'pizzip';
import Docxtemplater from 'docxtemplater';
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 库只支持文本的动态填充。如果需要插入图片,就需要额外安装并配置 ImageModuledocxtemplater-image-module-free 这是一个 npm 包的名称,它是 docxtemplater 的一个插件模块。核心功能允许将图片动态插入到 Word 模板中。适用配合 docxtemplater 使用,基于模板生成包含图片的 Word 文档。

二、具体实现代码

1、主程序代码

export async function ScreenShot(elID: string) {
    const element = document.getElementById(elID);

    if (!element) {
        console.error('Element not found!');
        return;
    }

    try {
        // 使用 html2canvas 截取元素并生成 Canvas
        const canvas = await html2canvas(element, {
            useCORS: true,
            scale: window.devicePixelRatio < 3 ? window.devicePixelRatio : 2,
            allowTaint: true,
        });

        // 将 Canvas 转换为 Base64 图片
        const imageBase64 = canvas.toDataURL('image/png');
        const imageblob = canvas.toBlob(function () { }, 'image/png')

        // 加载 Word 模板文件
        const response = await fetch('/template.docx'); // 模板路径
        const arrayBuffer = await response.arrayBuffer();

        // 使用 PizZip 解压模板
        const zip = new PizZip(arrayBuffer);

        const imageOptions = {
            getImage(tagValue: any) {
                return base64Parser(tagValue);
            },
            getSize(img: any, tagValue: any, tagName: any, context: any) {
                return [400, 240];
            },
            centered: true,
        };
        const doc = new Docxtemplater(zip, {
            modules: [new ImageModule(imageOptions)],
        });

        // 渲染模板
        doc.render({
            image: imageBase64, // 仅保留 Base64 数据部分
        });

        // 生成 Word 文件并下载
        const out = doc.getZip().generate({
            type: 'blob',
            mimeType:
                'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
        });

        saveAs(out, 'screenshot.docx');
    } catch (error) {
        console.error('Error generating Word document:', error);
    }
}

这段代码实现了一个截图功能,将 HTML 页面中的某个元素(由 elID 指定)截图并保存到Word文档中。具体步骤包括:

  1. 使用 html2canvas 将指定 HTML 元素转换为图片。
  2. 加载Word模板文件(template.docx)。
  3. 使用 docxtemplater 和 docxtemplater-image-module-free 插件将图片插入 Word 文档模板中。生成新的 Word 文件,并允许用户下载。

接下来进行拆解主程序代码,详细说明每一段代码实现的意义:

(1)函数的定义和参数:

定义一个异步函数ScreenShot,接受一个参数elID(要截图的HTML元素的 ID)。首先通过document.getElementById获取指定的DOM元素。如果找不到目标元素,打印错误并终止函数。

export async function ScreenShot(elID: string) {
    const element = document.getElementById(elID);
    if (!element) {
        console.error('Element not found!');
        return;
    }

(2)使用htmlcanvas截图:

html2canvas将 HTML 元素渲染为 Canvas 图像。useCORS: true:启用跨域支持,允许加载跨域的图片资源。scale: window.devicePixelRatio < 3 ? window.devicePixelRatio : 2:根据设备像素比调整图像分辨率,限制最大缩放比为2。allowTaint: true:允许跨域图片资源渲染到 Canvas(潜在安全问题)。输出一个Canvas 对象包含 HTML 元素的渲染结果。

const canvas = await html2canvas(element, {
    useCORS: true,
    scale: window.devicePixelRatio < 3 ? window.devicePixelRatio : 2,
    allowTaint: true,
});

(3)获取图片的 Base64数据和Blob:

toDataURL:将 Canvas 转换为 Base64 编码的 PNG 图片。用于将图片数据以文本形式嵌入到 Word 文档。toBlob:将 Canvas 转换为二进制 Blob 对象。可以用作图片文件保存或进一步操作。

const imageBase64 = canvas.toDataURL('image/png');
const imageblob = canvas.toBlob(function () { }, 'image/png');

(4)加载Word模板:

通过 fetch 请求加载 Word 模板文件。.docx 是 Word 文档的文件格式,本质上是一个 ZIP 文件。将响应转换为 arrayBuffer(字节数组),用于后续操作。(这里的template.docx是自己预先创建的文档,需要将该文档放在public根目录下,文档里需要写入图片的占位符{%image}

const response = await fetch('/template.docx');
const arrayBuffer = await response.arrayBuffer();

(5)解压模板文件:

 PizZip 是一个 ZIP 文件处理库,用于解压和操作 Word 模板。arrayBuffer 是模板文件的字节内容。解压后的 ZIP 文件结构,供 Docxtemplater 使用。

const zip = new PizZip(arrayBuffer);

(6)配置图片模板:

getImage:定义如何解析模板中的图片占位符数据。调用 base64Parser(自定义函数,后续会提到)解析 Base64 数据。getSize:定义图片尺寸。这里固定为宽 400px,高 240px。centered:指定图片在 Word 文档中的对齐方式,设置为居中。

const imageOptions = {
    getImage(tagValue: any) {
        return base64Parser(tagValue);
    },
    getSize(img: any, tagValue: any, tagName: any, context: any) {
        return [400, 240];
    },
    centered: true,
};

(7)渲染模板:

Docxtemplater 是一个模板引擎,用于动态填充 Word 文档。ImageModule 插件支持插入图片到 Word 模板。将 imageBase64(截图的 Base64 数据)绑定到模板中的图片占位符。

const doc = new Docxtemplater(zip, {
    modules: [new ImageModule(imageOptions)],
});
doc.render({
    image: imageBase64,
});

(8)生成并下载Word文件:

 type: 'blob':指定输出文件类型为二进制 Blob。mimeType:指定文件为 Word 文档(docx 格式)。使用 file-saver 库的 saveAs 方法将生成的 Word 文件提供给用户下载,文件名为 screenshot.docx。

const out = doc.getZip().generate({
    type: 'blob',
    mimeType:
        'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
});
saveAs(out, 'screenshot.docx');

(9)错误处理:

捕获并处理任何可能在截图、模板渲染或文件生成过程中发生的错误。保障代码在异常情况下不会崩溃,并提供调试信息。

catch (error) {
    console.error('Error generating Word document:', error);
}

2、相关函数代码

const base64Regex =
    /^(?:data:)?image\/(png|jpg|jpeg|svg|svg\+xml);base64,/;

const validBase64 =
    /^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$/;

function base64Parser(tagValue: any) {
    if (
        typeof tagValue !== "string" ||
        !base64Regex.test(tagValue)
    ) {
        return false;
    }

    const stringBase64 = tagValue.replace(base64Regex, "");

    if (!validBase64.test(stringBase64)) {
        throw new Error(
            "Error parsing base64 data, your data contains invalid characters"
        );
    }

    // For nodejs, return a Buffer
    if (typeof Buffer !== "undefined" && Buffer.from) {
        return Buffer.from(stringBase64, "base64");
    }

    // For browsers, return a string (of binary content) :
    const binaryString = window.atob(stringBase64);
    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;
}

这段代码定义了一个函数 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 编码数据。

const base64Regex =
    /^(?:data:)?image\/(png|jpg|jpeg|svg|svg\+xml);base64,/;

validBase64:  匹配纯 Base64 数据(即编码内容部分)。[A-Za-z0-9+/]{4}:每组 4 个字符,由字母、数字和 + 或 / 组成。末尾部分允许补齐字符:{2}==:2 个有效字符,后跟 2 个 =。{3}=:3 个有效字符,后跟 1 个 =。

const validBase64 =
    /^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$/;

(2)函数主体:

(a)验证输入数据是否为字符串,并且符合 Base64 图片数据的格式。条件 1:tagValue 必须是字符串。条件 2:tagValue 必须匹配 base64Regex。如果不符合上述条件,返回 false,表示数据无效。

function base64Parser(tagValue: any) {
    if (
        typeof tagValue !== "string" ||
        !base64Regex.test(tagValue)
    ) {
        return false;
    }

(b)将 Base64 数据的前缀部分移除,仅保留纯 Base64 编码内容。

示例:

输入:data:image/png;base64,ABC123...

输出:ABC123...

const stringBase64 = tagValue.replace(base64Regex, "");

(c)检查提取的base64数据是否有效格式,使用validbase64正则表达式验证纯base64数据。如果不匹配,抛出错误,提示数据包含无效字符。

if (!validBase64.test(stringBase64)) {
    throw new Error(
        "Error parsing base64 data, your data contains invalid characters"
    );
}

(3)数据解析:

 (a)在node.js的环境下,将base64数据解析为Buffer,仅当全局buffer对象存在,并且支持Buffer.from方法时执行,Buffer对象,适合在服务器端处理二进制数据。

if (typeof Buffer !== "undefined" && Buffer.from) {
    return Buffer.from(stringBase64, "base64");
}

(b)在浏览器环境下,将base64数据解析为ArrayBuffer。使用window.atob解码八涩数据为二进制字符串。创建Unit8Array,逐字节填充二进制数据。binaryString.charCodeAt(i): 获取字符的ASCII码值。返回Unit8Array.buffer,即ArrayBuffer对象。 

const binaryString = window.atob(stringBase64);
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;

三、存在的一些问题(还能在继续优化)

  • 图片尺寸调整:动态计算图片尺寸以适配模板占位符。
  • 错误提示友好化:在 UI 层提示用户错误信息,而非仅打印到控制台。
  • 模板路径动态化:允许用户选择模板文件,而非硬编码路径。
  • 错误提示优化:如果 base64Regex 不匹配,明确指出格式问题。提供示例说明正确的 Base64 图片数据格式。
  • 性能提升:在浏览器环境下,考虑使用更高效的 TextDecoder 替代 window.atob
  • 兼容性增强:如果目标环境是浏览器,考虑移除 Node.js 部分的代码,减少代码体积。

四、完整代码

import html2canvas from 'html2canvas';
import { saveAs } from 'file-saver';
import PizZip from 'pizzip';
import Docxtemplater from 'docxtemplater';
import ImageModule from 'docxtemplater-image-module-free';

export async function ScreenShot(elID: string) {
    const element = document.getElementById(elID);

    if (!element) {
        console.error('Element not found!');
        return;
    }

    try {
        // 使用 html2canvas 截取元素并生成 Canvas
        const canvas = await html2canvas(element, {
            useCORS: true,
            scale: window.devicePixelRatio < 3 ? window.devicePixelRatio : 2,
            allowTaint: true,
        });

        // 将 Canvas 转换为 Base64 图片
        const imageBase64 = canvas.toDataURL('image/png');
        const imageblob = canvas.toBlob(function () { }, 'image/png')

        // 加载 Word 模板文件
        const response = await fetch('/template.docx'); // 模板路径
        const arrayBuffer = await response.arrayBuffer();

        // 使用 PizZip 解压模板
        const zip = new PizZip(arrayBuffer);

        const imageOptions = {
            getImage(tagValue: any) {
                return base64Parser(tagValue);
            },
            getSize(img: any, tagValue: any, tagName: any, context: any) {
                return [400, 240];
            },
            centered: true,
        };
        const doc = new Docxtemplater(zip, {
            modules: [new ImageModule(imageOptions)],
        });

        // 渲染模板
        doc.render({
            image: imageBase64, // 仅保留 Base64 数据部分
        });

        // 生成 Word 文件并下载
        const out = doc.getZip().generate({
            type: 'blob',
            mimeType:
                'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
        });

        saveAs(out, 'screenshot.docx');
    } catch (error) {
        console.error('Error generating Word document:', error);
    }
}
const base64Regex =
    /^(?:data:)?image\/(png|jpg|jpeg|svg|svg\+xml);base64,/;

const validBase64 =
    /^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$/;

function base64Parser(tagValue: any) {
    if (
        typeof tagValue !== "string" ||
        !base64Regex.test(tagValue)
    ) {
        return false;
    }

    const stringBase64 = tagValue.replace(base64Regex, "");

    if (!validBase64.test(stringBase64)) {
        throw new Error(
            "Error parsing base64 data, your data contains invalid characters"
        );
    }

    // For nodejs, return a Buffer
    if (typeof Buffer !== "undefined" && Buffer.from) {
        return Buffer.from(stringBase64, "base64");
    }

    // For browsers, return a string (of binary content) :
    const binaryString = window.atob(stringBase64);
    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;
}

参考网址:Image module | docxtemplater

在 Vue3 中,将实时变化的数据适配为表格结构插入Word 文档中通常需要借助一些,如`xlsx`处理 Excel 格式的数据,`docxtemplater`或`puppeteer`处理 Word 文档。以下是一个基本步骤: 1. **安装所需依赖**: 使用 npm 或 yarn 安装 `axios`(用于请求数据)、`xlsx`(转换 JSON 到 Excel)以及处理 Word(例如 `docxtemplater`)。 ```bash npm install axios xlsx docxtemplater ``` 2. **获取处理实时数据**: 使用 `axios` 获取数据,然后解析成适合表格的形式。例如,假设数据是 JSON 对象数组: ```javascript async function fetchData() { const response = await axios.get('your-api-url'); const data = response.data.map(item => ({ column1: item.field1, column2: item.field2, // 添加其他列 })); } ``` 3. **创建 Excel 表格**: 使用 `xlsx` 将数据转化为 Excel 格式: ```javascript const workbook = XLSX.utils.book_new(); const worksheet = XLSX.utils.json_to_sheet(data); XLSX.utils.book_append_sheet(workbook, worksheet, 'Sheet1'); // 设置工作表名 // 导出为 blob 或文件流 let excelBuffer = XLSX.write(workbook, { type: 'buffer' }); ``` 4. **插入 Word 文档**: 如果你想用模板,可以使用 `docxtemplater`,首先准备一个.docx 文件作为模板,里面包含表格字段标记 `{field_name}`。然后加载模板,替换数据: ```javascript const doc = new Docxtemplater('template.docx'); data.forEach(item => { doc.setData(item); }); doc.render(function(err, results) { if (err) throw err; // 将生成的内容写入新的 Word 文档 const wordDoc = results[0].word; // 可能还需要添加到特定位置,或者导出为文件流 }); ``` 5. **保存或下载**: 最后,你可以选择将生成的 Word 文档内容直接显示在网页上、或者提供下载链接给用户。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值