欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 文旅 > 美景 > html-docx-js和file-saver实现html导出word

html-docx-js和file-saver实现html导出word

2024/11/30 10:41:16 来源:https://blog.csdn.net/oucqsy/article/details/140655099  浏览:    关键词:html-docx-js和file-saver实现html导出word

依赖html-docx-js,file-saver,html2canvas

import { asBlob } from 'html-docx-js/dist/html-docx';
import { saveAs } from 'file-saver';
import html2Canvas from 'html2canvas';const handleImageToBase64 = (cloneEle) => {let imgElements = cloneEle.getElementsByTagName('img');let canvas = document.createElement('canvas');let ctx = canvas.getContext('2d');Array.from(imgElements).forEach((item) => {canvas.width = item.width;canvas.height = item.height;ctx.drawImage(item, 0, 0, item.width, item.height);let ext = item.src.substring(item.src.lastIndexOf('.') + 1).toLowerCase();let dataURL = canvas.toDataURL('image/' + ext);item.setAttribute('src', dataURL);});canvas.remove();
};const handleCanvasToImage = (cloneEle) => {const canvasElements = cloneEle.getElementsByTagName('canvas');const promises = Array.from(canvasElements).map((ca, index) => {return new Promise((resolve) => {const url = ca.toDataURL('image/png', 1);const img = new Image();img.onload = () => {URL.revokeObjectURL(url);resolve();};img.src = url;// 生成img插入clone的dom的canvas之前canvasElements[index].parentNode.insertBefore(img, canvasElements[index]);});});// 移除原来的canvasArray.from(canvasElements).forEach((ca) => ca.parentNode.removeChild(ca));return promises;
};const handleSvgToImage = (cloneEle) => {const svgElements = cloneEle.getElementsByTagName('svg');Array.from(svgElements).forEach((svg) => {// 将SVG元素转换为PNG图片const img = new Image();img.src = 'data:image/svg+xml;base64,' + window.btoa(encodeURIComponent(svg.outerHTML).replace(/%([0-9A-F]{2})/g, function(match, p1) {return String.fromCharCode('0x' + p1);}));// 将图片插入到SVG元素的位置svg.parentNode.insertBefore(img, svg);// 移除原来的SVG元素svg.parentNode.removeChild(svg);});
};const handleCodeToImage = (ele, cloneEle) => {let codeElements = ele.querySelectorAll('pre code');let cloneCodeElements = cloneEle.querySelectorAll('pre code');const promises = Array.from(codeElements).map((item, index) => {return new Promise((resolve) => {const pre = item.parentNode;html2Canvas(pre, {imageTimeout: 2000,logging: false,scrollY: 0,scrollX: 0,scale: window.devicePixelRatio * 1.2, // 添加的scale 参数width: ele.clientWidth / 1.5,allowTaint: false,useCORS: true, // 开启跨域}).then(canvas => {// 将 Canvas 转换为图片let dataURL = canvas.toDataURL('image/png');// 创建一个新的 <img> 元素并设置其 src 属性const img = new Image();img.src = dataURL;// 将图片插入到SVG元素的位置const clonePre = cloneCodeElements[index].parentNode;clonePre.parentNode.insertBefore(img, clonePre);// 移除原来的SVG元素clonePre.parentNode.removeChild(clonePre);resolve();});});});return promises;
};// 表格虚线 向右偏移10px左右
const handleTableStyle = (cloneEle) => {let tableElements = cloneEle.getElementsByTagName('table');Array.from(tableElements).forEach((table) => {table.style.borderCollapse = table.style.borderCollapse || 'collapse';table.border = table.border || '1';table.style.marginLeft = '10px';});let thElements = cloneEle.getElementsByTagName('th');Array.from(thElements).forEach((th) => {th.style.backgroundColor = '#f0f0f0';});
};const getCss = () => {return `body {color: #383c4a;font-family: -apple-system, blinkmacsystemfont, "Segoe UI", helvetica, arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji";font-size: 12px;word-wrap: break-word;}`;
};const handleHtml = async (ele, cloneEle) => {const canvasPromises = handleCanvasToImage(cloneEle);handleSvgToImage(cloneEle);const codePromises = handleCodeToImage(ele, cloneEle);await Promise.all(canvasPromises);await Promise.all(codePromises);handleImageToBase64(cloneEle);handleTableStyle(cloneEle);let cssString = '';cssString = getCss();const innerHtml = cloneEle.outerHTML// strong在word中不生效问题.replace(/<strong class="(.*?)">(.*?)<\/strong>/g, '<b class="$1">$2</b>').replace(/<mark/g, '<span').replace(/<\/mark>/g, '</span>');const htmlString = `<html xmlns:o="urn:schemas-microsoft-com:office:office" xmlns:w="urn:schemas-microsoft-com:office:word" xmlns="http://www.w3.org/TR/REC-html40"><head><style type="text/css">${cssString}</style> </head><body>${innerHtml}</body></html>`;return htmlString;
};export default function exportWord({ selector, name = 'export' }) {if (!selector) return Promise.reject();// eslint-disable-next-line no-async-promise-executorreturn new Promise(async (resolve) => {const ele = document.querySelector(selector);const cloneEle = ele.cloneNode(true);const htmlString = await handleHtml(ele, cloneEle);const converted = asBlob(htmlString);saveAs(converted, `${name}.docx`);resolve();});}

页面调用

exportWord({selector: '.report-container'});

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com