使用html2pdf生成PDF并通过Ajax发送至PHPMailer的完整教程

使用html2pdf生成PDF并通过Ajax发送至PHPMailer的完整教程

本教程详细介绍了如何利用JavaScripthtml2pdf在客户端生成PDF文档,并将其以Base64编码字符串的形式通过ajax异步发送至服务器。在服务器端,我们将使用php处理接收到的Base64数据,去除URI前缀后进行解码,最终通过PHPMailer库将生成的PDF作为附件发送电子邮件。本文将涵盖从前端PDF生成、数据传输到后端处理和邮件发送的全过程,并提供完整的代码示例和注意事项。

1. 概述与准备工作

在web应用中,有时我们需要将用户界面上的内容转换为pdf文档,并将其通过邮件发送。直接在客户端生成并发送邮件是不安全的,也无法实现。因此,常见的做法是:在客户端生成pdf的二进制数据(通常是base64编码),通过ajax发送到服务器,再由服务器端脚本(如php)处理并发送邮件。

本教程将使用以下关键技术

  • 前端: html2pdf.JS (基于html2canvas和jsPDF) 用于将HTML内容转换为PDF,jquery 或原生 XMLhttpRequest 进行Ajax通信。
  • 后端: PHP 处理数据,PHPMailer 库发送电子邮件。

在开始之前,请确保你的项目已引入 html2pdf.js 和 jQuery (如果使用),并且服务器端已安装 PHPmailer。

2. 客户端:生成PDF并以Base64字符串形式传输

在客户端,我们首先使用html2pdf.js将指定的html元素内容转换为PDF。关键在于不直接保存PDF,而是将其输出为Base64编码的URI字符串。

2.1 HTML结构准备

确保你的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>

2.2 JavaScript代码:生成Base64 PDF并发送Ajax请求

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生成或发送失败。");     } });

代码解释:

  • html2pdf().from(page).set(pdfOptions).outputPdf(‘datauristring’): 这是核心部分。它指示 html2pdf 从 page 元素生成PDF,应用 pdfOptions 配置,并将结果输出为 datauristring。
  • datauristring 格式通常是 data:application/pdf;base64,JVBERi…,其中 JVBERi… 是PDF的Base64编码内容。服务器端需要处理这个前缀。
  • await 关键字用于等待异步的 html2pdf 操作完成。为了使用 await,你的函数需要被声明为 async。
  • $.ajax() 用于发送POST请求,将 pdfContent 作为数据的一部分发送到服务器。

3. 服务器端:处理Base64 PDF数据并使用PHPMailer发送邮件

在服务器端(PHP脚本),我们将接收前端发送过来的Base64字符串,进行解码,然后使用PHPMailer将其作为附件发送。

3.1 PHP代码:接收、解码并发送邮件

<?php // 引入 PHPMailer 相关的类文件 use PHPMailerPHPMailerPHPMailer; use PHPMailerPHPMailerException;  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}"]); } ?>

代码解释:

  • PHPMailer 引入: 确保 require 语句指向你的PHPMailer库的正确路径。
  • 数据提取: $_POST[‘pdfContent’] 获取前端发送的Base64字符串。
  • substr($pdfdoc, strpos($pdfdoc, ‘,’) + 1): 这是关键一步。datauristring 格式包含一个前缀(例如 data:application/pdf;base64,),我们需要用 strpos 找到逗号的位置,然后用 substr 从逗号之后开始截取,从而得到纯粹的Base64编码数据。
  • base64_decode($pdfData): 将纯粹的Base64编码数据解码回原始的二进制PDF数据。
  • $mail->AddStringAttachment(…): 这是PHPMailer中用于添加字符串作为附件的方法。
    • 第一个参数 $decodedPdf 是解码后的二进制PDF数据。
    • 第二个参数 “GeneratedDocument.pdf” 是附件的文件名。
    • 第三个参数 “base64” 表示附件的编码方式(尽管我们传入的是解码后的数据,PHPMailer内部会根据这个参数进行处理,这里指明原始数据是Base64编码的)。
    • 第四个参数 “application/pdf” 是附件的MIME类型,这非常重要,它告诉邮件客户端这是一个PDF文件。
  • SMTP 配置: 替换 host, username, password, port, SMTPSecure 为你的SMTP服务器的实际配置。
  • 错误处理: try…catch 块用于捕获PHPMailer可能抛出的异常,并返回详细的错误信息。

4. 注意事项与总结

  • 文件大小限制: 通过Ajax发送Base64编码的数据会显著增加数据量(Base64编码会使数据量增大约33%)。对于非常大的PDF文件,这可能会导致HTTP请求体过大,超出服务器或Web服务器(如nginx, apache)的请求体大小限制。你可能需要调整服务器配置(例如PHP的 post_max_size 和 upload_max_filesize,以及Web服务器的 client_max_body_size)。
  • 安全性:
    • 始终在服务器端验证所有接收到的输入数据,包括邮件地址、主题和内容,以防止注入攻击(如XSS)。
    • 不要直接暴露你的SMTP凭据在客户端代码中。PHPMailer配置应完全在服务器端进行。
    • 考虑对生成的PDF内容进行服务器端验证或消毒,如果内容来源于用户输入。
  • 异步操作: html2pdf 的生成过程是异步的。确保你在发送Ajax请求之前,PDF内容已经完全生成并赋值给 pdfContent 变量。使用 await 或 .then() 回调是处理异步操作的正确方式。
  • MIME 类型: 在 AddStringAttachment 中正确指定 application/pdf MIME 类型至关重要,它能确保邮件客户端正确识别并显示附件。
  • 调试: 在开发阶段,将 PHPMailer 的 SMTPDebug 设置为 1 或 2 可以帮助你查看SMTP通信过程,从而诊断连接或认证问题。在生产环境中,务必将其设置为 0。
  • PHPMailer 路径: 确保 require 语句中PHPMailer库的路径是正确的。

通过以上步骤,你就可以成功地在客户端生成PDF,并通过Ajax将其发送到服务器,再由PHPMailer将其作为附件发送电子邮件。这种方法兼顾了客户端生成PDF的灵活性和服务器端发送邮件的可靠性与安全性。

使用html2pdf生成PDF并通过Ajax发送至PHPMailer的完整教程

以上就是使用html2pdf生成PDF并通过Ajax发送至PHPM

© 版权声明
THE END
喜欢就支持一下吧
点赞14 分享