如何从含可交互SVG的网页生成带高亮笔记的PDF并发送至用户邮箱
可行实现方案
失效根因
所有纯服务端的HTML转PDF工具(Dompdf、wkhtmltopdf等)只能渲染初始页面的静态HTML,无法获取前端JS动态修改的SVG实时高亮样式,因此输出的PDF必然不符合预期。
分步实现流程
1. 前端改造逻辑
- 隐藏无需导出的元素:点击生成后,先把所有按钮、弹窗表单设置为
display: none,仅保留SVG画布和待导出的笔记区域 - 解决SVG跨域问题:由于SVG内嵌了远程基础图,若直接截图会出现加载失败,两种解决方案二选一:
- 截图时开启
useCORS: true配置 - 将远程基础图下载到本地服务器存储,替换SVG中的远程图片地址
- 截图时开启
- 调用
html2canvas对可见导出区域截图,设置2倍缩放保证清晰度:
const exportArea = document.querySelector("#exportWrap"); html2canvas(exportArea, { useCORS: true, scale: 2, backgroundColor: "#ffffff" }).then(canvas => { // 后续生成PDF逻辑 });
2. 组装PDF内容
用截图得到的Canvas生成PDF,将用户填写的笔记自动追加到PDF下方,保证和网页显示完全一致:
import { jsPDF } from "jspdf"; const imgData = canvas.toDataURL("image/png"); const pdf = new jsPDF("p", "mm", "a4"); // 按A4纸宽度自适应插入SVG截图 pdf.addImage(imgData, "PNG", 10, 10, 190, 138); // 自动换行插入用户填写的笔记 const userNotes = document.querySelector("#ActionBody").value; pdf.text(10, 160, userNotes, { maxWidth: 190 });
3. 导出并提交数据
将生成的PDF转为Base64编码,和用户输入的邮箱一起POST到后端接口,避免二进制文件传输兼容问题:
// 给原有邮箱输入框添加id="emailInput"后获取值 const userEmail = document.querySelector("#emailInput").value; // PDF转Base64 const pdfBase64 = pdf.output("datauristring").split(",")[1]; // 提交到后端 fetch("/generate-pdf.php", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ userEmail, pdfBase64, userNotes }) });
4. 后端发邮件
后端不需要再做HTML转PDF操作,直接将前端传来的PDF Base64解码后作为附件,用PHPMailer发送到用户邮箱:
// 后端接收数据 $input = json_decode(file_get_contents("php://input"), true); $userEmail = $input["userEmail"]; $pdfBinary = base64_decode($input["pdfBase64"]); // PHPMailer发送附件逻辑,省略初始化配置 $mail->addStringAttachment($pdfBinary, "stack-selection.pdf"); $mail->addAddress($userEmail); $mail->Subject = "你的方块选择PDF"; $mail->Body = "附件为你生成的带高亮选择和备注的PDF文件。"; $mail->send();
原有代码调整注意点
- 移除前端引入的SMTP.js,不要在前端发邮件,避免SMTP密钥暴露
- 生成按钮添加点击事件串联上述逻辑,不要直接触发弹窗
- 测试时先检查SVG远程图是否能正常加载,若CORS限制无法解决,直接把图存到本地
内容的提问来源于stack exchange,提问作者Heba
相关产品推荐
相关产品推荐

