在web应用中,有时我们需要将用户界面上的内容转换为pdf文档,并将其通过邮件发送。直接在客户端生成并发送邮件是不安全的,也无法实现。因此,常见的做法是:在客户端生成pdf的二进制数据(通常是base64编码),通过ajax发送到服务器,再由服务器端脚本(如php)处理并发送邮件。
本教程将使用以下关键技术栈:
在开始之前,请确保你的项目已引入 html2pdf.js 和 jQuery (如果使用),并且服务器端已安装 PHPMailer。
在客户端,我们首先使用html2pdf.js将指定的HTML元素内容转换为PDF。关键在于不直接保存PDF,而是将其输出为Base64编码的URI字符串。
确保你的HTML页面中有一个包含需要转换为PDF内容的元素,例如:
立即学习“PHP免费学习笔记(深入)”;
<div id="printPage"> <h1>这是一个PDF标题</h1> <p>这是需要转换为PDF的内容。</p> <ul> <li>列表项1</li> <li>列表项2</li> </ul> @@##@@ </div> <button id="sendPdfBtn">生成并发送PDF</button>
html2pdf.js 提供了一个 output() 方法,可以指定输出格式。我们使用 datauristring 格式来获取PDF的Base64编码字符串。
// 获取需要转换为PDF的HTML元素 let page = document.getElementById('printPage'); // html2pdf 配置选项 var pdfOptions = { margin: [5, 0, 0, 0], // 上右下左边距 filename: 'document.pdf', // 尽管不直接保存,但此文件名会作为附件默认名 image: { type: 'jpeg', quality: 1 // 图片质量 }, pagebreak: { mode: ['legacy'] // 分页模式 }, html2canvas: { scale: 3 // html2canvas 渲染比例 }, jsPDF: { unit: 'mm', // 单位 format: 'a4', // 纸张格式 orientation: 'portrait' // 方向:纵向 } }; // 监听按钮点击事件 $(document).on('click', '#sendPdfBtn', async function() { let pdfContent; try { // 使用 await 等待 PDF 生成为 datauristring pdfContent = await html2pdf().from(page).set(pdfOptions).outputPdf('datauristring'); // 或者使用 .then() 回调方式 // await html2pdf().from(page).set(pdfOptions).outputPdf('datauristring').then(function(pdfAsString) { // pdfContent = pdfAsString; // }); // 准备 Ajax 请求数据 let ajaxUrl = 'your_php_mailer_script.php'; // 替换为你的PHP脚本URL let transaction = 'someTransactionType'; // 示例数据 let transactionId = '12345'; // 示例数据 $.ajax({ type: "POST", url: ajaxUrl, data: { action: "sendEmail", // 示例动作 transaction: transaction, transactionId: transactionId, emailTo: $("#emailTo").val() || "recipient@example.com", // 接收者邮箱 emailCc: $("#emailCc").val(), // 抄送 emailBcc: $("#emailBcc").val(), // 密送 emailSubject: $("#emailSubject").val() || "来自网站的PDF报告", // 邮件主题 emailMessage: $("#emailMessage").val() || "请查收附件中的PDF文档。", // 邮件内容 pdfContent: pdfContent // 核心:Base64编码的PDF内容 }, success: function(data) { console.log("邮件发送响应:", data); alert("邮件发送成功!"); }, error: function(xhr, status, error) { console.error("Ajax请求失败:", status, error); alert("邮件发送失败,请查看控制台了解详情。"); } }); } catch (error) { console.error("PDF生成或发送过程中发生错误:", error); alert("PDF生成或发送失败。"); } });
代码解释:
在服务器端(PHP脚本),我们将接收前端发送过来的Base64字符串,进行解码,然后使用PHPMailer将其作为附件发送。
<?php // 引入 PHPMailer 相关的类文件 use PHPMailer\PHPMailer\PHPMailer; use PHPMailer\PHPMailer\Exception; require 'path/to/PHPMailer/src/Exception.php'; require 'path/to/PHPMailer/src/PHPMailer.php'; require 'path/to/PHPMailer/src/SMTP.php'; // 设置响应头,防止CORS问题或确保JSON响应 header('Content-Type: application/json'); // 检查是否是POST请求 if ($_SERVER['REQUEST_METHOD'] !== 'POST') { echo json_encode(['status' => 'error', 'message' => 'Invalid request method.']); exit; } // 获取前端发送的PDF内容及其他邮件信息 $pdfdoc = $_POST['pdfContent'] ?? ''; $emailTo = $_POST['emailTo'] ?? ''; $emailCc = $_POST['emailCc'] ?? ''; $emailBcc = $_POST['emailBcc'] ?? ''; $emailSubject = $_POST['emailSubject'] ?? '邮件主题未设置'; $emailMessage = $_POST['emailMessage'] ?? '邮件内容为空'; // 验证PDF内容是否存在 if (empty($pdfdoc)) { echo json_encode(['status' => 'error', 'message' => 'PDF content is missing.']); exit; } // 提取Base64编码的PDF数据 // 'data:application/pdf;base64,' 这个前缀需要被移除 $pdfData = substr($pdfdoc, strpos($pdfdoc, ',') + 1); // 从逗号后面开始截取 // 对Base64数据进行解码 $decodedPdf = base64_decode($pdfData); // 检查解码是否成功 if ($decodedPdf === false) { echo json_encode(['status' => 'error', 'message' => 'Failed to decode PDF content.']); exit; } // PHPMailer 实例 $mail = new PHPMailer(true); // true enables exceptions try { // 服务器设置 (根据你的SMTP服务商配置) $mail->SMTPDebug = 0; // 0 = off (for production), 1 = client messages, 2 = client and server messages $mail->isSMTP(); // 使用SMTP $mail->Host = 'smtp.yourdomain.com'; // SMTP 服务器地址 $mail->SMTPAuth = true; // 启用SMTP认证 $mail->Username = 'your_email@yourdomain.com'; // SMTP 用户名 $mail->Password = 'your_email_password'; // SMTP 密码 $mail->SMTPSecure = PHPMailer::ENCRYPTION_STARTTLS; // 启用TLS加密,或者 PHPMailer::ENCRYPTION_SMTPS for SSL $mail->Port = 587; // TLS 端口通常是 587,SSL 端口通常是 465 // 收件人 $mail->setFrom('sender@yourdomain.com', 'Your Company Name'); // 发件人邮箱和名称 $mail->addAddress($emailTo); // 收件人邮箱 if (!empty($emailCc)) { $mail->addCC($emailCc); // 抄送 } if (!empty($emailBcc)) { $mail->addBCC($emailBcc); // 密送 } // 附件 // AddStringAttachment(string $string, string $filename, string $encoding = 'base64', string $type = '', string $disposition = 'attachment') // 这里我们传入的是原始的二进制PDF数据,所以编码类型是 'base64' (因为它之前是base64编码的),MIME类型是 'application/pdf' $mail->AddStringAttachment($decodedPdf, "GeneratedDocument.pdf", "base64", "application/pdf"); // 内容 $mail->isHTML(true); // 邮件内容为HTML格式 $mail->Subject = $emailSubject; // 邮件主题 $mail->Body = nl2br(htmlspecialchars($emailMessage)); // 邮件HTML内容,nl2br保留换行,htmlspecialchars防止XSS $mail->AltBody = strip_tags($emailMessage); // 纯文本内容,用于不支持HTML的邮件客户端 $mail->send(); echo json_encode(['status' => 'success', 'message' => 'Message has been sent.']); } catch (Exception $e) { echo json_encode(['status' => 'error', 'message' => "Message could not be sent. Mailer Error: {$mail->ErrorInfo}"]); } ?>
代码解释:
通过以上步骤,你就可以成功地在客户端生成PDF,并通过Ajax将其发送到服务器,再由PHPMailer将其作为附件发送电子邮件。这种方法兼顾了客户端生成PDF的灵活性和服务器端发送邮件的可靠性与安全性。
以上就是使用html2pdf生成PDF并通过Ajax发送至PHPMailer的完整教程的详细内容,更多请关注php中文网其它相关文章!
全网最新最细最实用WPS零基础入门到精通全套教程!带你真正掌握WPS办公! 内含Excel基础操作、函数设计、数据透视表等
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号