
在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>
<img src="your_image.png" alt="示例图片">
</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号