import html2canvas from "html2canvas"; import jsPDF from "jspdf"; import { pdfToText } from "pdf-ts"; export async function htmlToPdf2(htmlCode: string) { const container = document.createElement("div"); container.style.cssText = ` position: fixed; left: -9999px; top: -9999px; width: 210mm; // 固定 A4 宽度 background: white; `; container.innerHTML = htmlCode; document.body.appendChild(container); try { // 关键修改 1: 确保所有图片加载完成 await waitForImages(container); // 关键修改 2: 强制触发布局计算 void container.offsetHeight; const canvas = await html2canvas(container, { scale: 2, useCORS: true, logging: true, scrollY: -window.scrollY, // 消除滚动偏移 windowWidth: container.scrollWidth, windowHeight: container.scrollHeight, }); const pdf = new jsPDF("p", "mm", "a4"); const pageWidth = pdf.internal.pageSize.getWidth(); const imgRatio = canvas.width / canvas.height; // 关键修改 3: 动态计算高度 const imgHeight = (pageWidth * canvas.height) / canvas.width; pdf.addImage( canvas.toDataURL("image/png"), "PNG", 0, 0, pageWidth, imgHeight, ); // 关键修改 4: 处理多页内容 if (imgHeight > pdf.internal.pageSize.getHeight()) { pdf.addPage(); pdf.addImage( canvas.toDataURL("image/png"), "PNG", 0, -pdf.internal.pageSize.getHeight(), pageWidth, imgHeight, ); } pdf.save("document.pdf"); } catch (error) { console.error("生成失败:", error); } finally { document.body.removeChild(container); } } // 图片加载等待函数 const waitForImages = (element: HTMLElement) => { return new Promise<void>((resolve) => { const images = element.getElementsByTagName("img"); let loaded = 0; const checkDone = () => { if (loaded >= images.length) resolve(); }; if (images.length === 0) return resolve(); Array.from(images).forEach((img) => { if (img.complete) { loaded++; checkDone(); } else { img.onload = () => { loaded++; checkDone(); }; img.onerror = checkDone; } }); }); }; export function htmlToPdf(htmlCode: string) { // 1. 动态创建一个 div 元素,并配置为隐藏(display: none) const container = document.createElement("div"); container.innerHTML = htmlCode; container.style.display = "none"; document.body.appendChild(container); // 2. 为了让 html2canvas 能捕获内容,将 display 修改为 block,并移至视野之外 container.style.display = "block"; container.style.position = "absolute"; container.style.top = "-9999px"; container.style.left = "-9999px"; window.pageYOffset = 0; document.documentElement.scrollTop = 0; document.body.scrollTop = 0; setTimeout(() => { html2canvas(container, { allowTaint: true, useCORS: true, scale: 2, // 提升画面质量,但是会增加文件大小 height: container.scrollHeight, // 需要注意,element的 高度 宽度一定要在这里定义一下,不然会存在只下载了当前你能看到的页面 避雷避雷!!! windowHeight: container.scrollHeight, }).then(function (canvas) { var contentWidth = canvas.width; var contentHeight = canvas.height; // console.log('contentWidth', contentWidth) // console.log('contentHeight', contentHeight) // 一页pdf显示html页面生成的canvas高度; var pageHeight = (contentWidth * 841.89) / 592.28; // 未生成pdf的html页面高度 var leftHeight = contentHeight; // console.log('pageHeight', pageHeight) // console.log('leftHeight', leftHeight) // 页面偏移 var position = 0; // a4纸的尺寸[595.28,841.89],html页面生成的canvas在pdf中图片的宽高 //40是左右页边距 var imgWidth = 595.28 - 40; var imgHeight = (592.28 / contentWidth) * contentHeight; var pageData = canvas.toDataURL("image/jpeg", 1.0); var pdf = new jsPDF("p", "pt", "a4"); // 有两个高度需要区分,一个是html页面的实际高度,和生成pdf的页面高度(841.89) // 当内容未超过pdf一页显示的范围,无需分页 if (leftHeight < pageHeight) { // console.log('没超过1页') pdf.addImage(pageData, "JPEG", 20, 20, imgWidth, imgHeight); } else { while (leftHeight > 0) { // console.log('超过1页') pdf.addImage(pageData, "JPEG", 20, position, imgWidth, imgHeight); leftHeight -= pageHeight; position -= 841.89; // 避免添加空白页 if (leftHeight > 0) { pdf.addPage(); } } } pdf.save("out.pdf"); }); }, 1000); } export async function getPdfData(file: File) { try { const arrayBuffer = await file.arrayBuffer(); const text = await pdfToText(new Uint8Array(arrayBuffer)); return text; } catch (error) { console.error("Error extracting PDF content:", error); throw error; } }