如何在客户端用vanilla JS实现HTML转PDF并转Base64供EmailJS发邮件
纯前端HTML转PDF并输出Base64实现方案(Vanilla JS)
核心实现逻辑
- 第一步:通过DOM转Canvas能力渲染发票页面内容,保证样式和页面展示完全一致
- 第二步:将Canvas内容写入PDF实例生成标准PDF二进制流
- 第三步:提取PDF二进制流的Base64内容,直接适配EmailJS的附件要求
完整代码实现
首先在页面中引入两个纯JS依赖(无框架绑定,符合Vanilla JS使用要求):
<!-- 用于将DOM节点转换为Canvas --> <script src="https://cdnjs.cloudflare.com/ajax/libs/html2canvas/1.4.1/html2canvas.min.js"></script> <!-- 用于生成标准PDF文件 --> <script src="https://cdnjs.cloudflare.com/ajax/libs/jspdf/2.5.1/jspdf.umd.min.js"></script>
点击「发送邮件」按钮的触发逻辑:
document.querySelector('#send-email-btn').addEventListener('click', async () => { // 替换为你的发票页面容器DOM节点 const invoiceElement = document.querySelector('#invoice-wrapper'); // 1. 将发票DOM转为Canvas const canvas = await html2canvas(invoiceElement, { scale: 2, // 调整清晰度,数值越高文件体积越大 useCORS: true, // 允许加载跨域图片,发票包含外部资源时必须开启 logging: false }); // 2. 初始化PDF实例,A4竖版,单位毫米 const { jsPDF } = window.jspdf; const pdfInstance = new jsPDF('p', 'mm', 'a4'); // 计算Canvas适配A4尺寸的宽高 const a4Width = 210; const a4Height = 297; const renderHeight = canvas.height * a4Width / canvas.width; let remainingHeight = renderHeight; let offsetY = 0; // 3. 写入PDF内容,自动处理分页 pdfInstance.addImage(canvas.toDataURL('image/png'), 'PNG', 0, offsetY, a4Width, renderHeight); remainingHeight -= a4Height; while (remainingHeight > 0) { offsetY = remainingHeight - renderHeight; pdfInstance.addPage(); pdfInstance.addImage(canvas.toDataURL('image/png'), 'PNG', 0, offsetY, a4Width, renderHeight); remainingHeight -= a4Height; } // 4. 转换为EmailJS要求的无前缀Base64格式 const pdfBase64 = pdfInstance.output('datauristring').split(',')[1]; // 5. 调用EmailJS发送带附件的邮件,替换为你自己的服务、模板、公钥参数 emailjs.send('你的服务ID', '你的模板ID', { recipient: '客户邮箱地址', attachments: [ { name: '消费发票.pdf', data: pdfBase64 } ] }, '你的EmailJS公钥') .then(() => alert('发票邮件发送成功')) .catch(err => console.error('发送失败:', err)); });
注意事项
- 如果发票包含外部图片/字体资源,需要确保资源配置了跨域许可,否则html2canvas会渲染失败
- 如果你不想引入任何外部依赖,可以用浏览器原生
window.print()API生成PDF,但原生API无法直接返回Base64内容,需要用户手动操作,不符合自动发送的场景需求 - 不需要分页的场景可以直接删除分页逻辑,生成单页PDF即可
- 不要省略Base64前缀的切割步骤,EmailJS不接收带
data:application/pdf;base64,前缀的内容
内容的提问来源于stack exchange,提问作者codes
相关产品推荐
相关产品推荐

