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

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

本教程詳細介紹了如何利用 JavaScripthtml2pdf 在客戶端生成 PDF 文件,并將其以數據 URI 字符串的形式通過 ajax 異步發送至 php 后端。在服務器端,我們將學習如何接收并解析這份 PDF 數據,最終使用 PHPMailer 庫將其作為附件發送電子郵件。文章涵蓋了從前端數據準備到后端文件處理及郵件發送的完整流程,并提供了關鍵代碼示例和注意事項。

在現代 web 應用中,用戶可能需要將頁面內容導出為 pdf 并通過郵件發送。直接在客戶端保存 pdf 相對簡單,但要將生成的 pdf 發送到服務器并作為郵件附件,則需要一套完整的客戶端與服務器端協作機制。本文將詳細闡述如何結合 html2pdf.JS、ajax 和 phpmailer 實現這一功能。

1. 客戶端 PDF 生成與數據準備 (JavaScript)

html2pdf.js 庫能夠將 HTML 內容轉換為 PDF。其核心在于 outputPdf() 方法,特別是當它與 ‘datauriString’ 參數結合使用時,可以將生成的 PDF 內容以 Base64 編碼的字符串形式返回,這正是通過 Ajax 傳輸的理想格式。

首先,確保你的頁面中有一個 HTML 元素作為 PDF 的內容源,例如:

<div id="printPage">     <!-- 這里是你要轉換為PDF的內容 -->     <h1>報告標題</h1>     <p>這是一段示例文本,將包含在PDF中。</p>     <table>         <thead>             <tr><th>列1</th><th>列2</th></tr>         </thead>         <tbody>             <tr><td>數據A</td><td>數據B</td></tr>         </tbody>     </table> </div>

接下來是 JavaScript 代碼,用于生成 PDF 字符串并準備 Ajax 請求。請注意,html2pdf() 操作是異步的,因此我們需要使用 await 或 .then() 來確保在發送 Ajax 請求之前 PDF 內容已經完全生成。

立即學習PHP免費學習筆記(深入)”;

// 獲取要轉換為PDF的html元素 const page = document.getElementById('printPage');  // html2pdf 配置選項 const pdfOptions = {     margin: [5, 0, 0, 0], // 上、右、下、左邊距     filename: 'generated_document.pdf', // 盡管此處設置了文件名,但發送時可能需要服務器端重新指定     image: { type: 'jpeg', quality: 1 },     pagebreak: { mode: ['legacy'] }, // 分頁模式     html2canvas: { scale: 3 }, // html2canvas 渲染比例     jsPDF: { unit: 'mm', format: 'a4', orientation: 'portrait' } // jsPDF 庫配置 };  let pdfContent;  // 異步函數,用于生成PDF并發送Ajax請求 async function sendPdfViaAjax() {     try {         // 使用 outputPdf('datauristring') 獲取Base64編碼的PDF字符串         // await 確保在獲取到pdfAsString后再繼續執行         pdfContent = await html2pdf().from(page).set(pdfOptions).outputPdf('datauristring');          // 構建Ajax請求數據         const requestData = {             action: "sendEmail", // 服務器端用于識別操作的參數             // 其他需要發送的郵件信息,例如:             transaction: "some_transaction_data",             transactionId: "12345",             emailTo: $("#emailTo").val(),             emailCc: $("#emailCc").val(),             emailBcc: $("#emailBcc").val(),             emailSubject: $("#emailSubject").val(),             emailMessage: $("#emailMessage").val(),             pdfContent: pdfContent // 將Base64編碼的PDF字符串作為參數發送         };          // 發送Ajax POST請求到后端         $.ajax({             type: "POST",             url: ajaxUrl, // 你的后端處理腳本URL             data: requestData,             success: function(response) {                 console.log("郵件發送成功:", response);                 alert("郵件已成功發送!");             },             error: function(xhr, status, error) {                 console.error("郵件發送失敗:", error);                 alert("郵件發送失敗,請稍后再試。");             }         });     } catch (error) {         console.error("生成PDF或發送Ajax時出錯:", error);         alert("操作失敗,請檢查控制臺信息。");     } }  // 觸發發送的事件監聽器,例如一個按鈕點擊事件 $(document).on('click', '#sendEmailBtn', function() {     sendPdfViaAjax(); });

在上述代碼中,outputPdf(‘datauristring’) 是關鍵。它會返回一個形如 data:application/pdf;base64,JVBERi… 的字符串。這個字符串包含了 PDF 的 MIME 類型前綴和 Base64 編碼的實際 PDF 數據。

2. 服務器端 PDF 處理與郵件發送 (PHP with PHPMailer)

在 PHP 后端,我們需要接收前端發送過來的 pdfContent 字符串,對其進行解析,然后使用 PHPMailer 將其作為附件添加到郵件中。

<?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';  // 假設這是你的Ajax處理入口 if (isset($_POST['action']) && $_POST['action'] === 'sendEmail') {     // 接收前端發送的PDF內容及其他郵件信息     $pdfdoc = $_POST['pdfContent'] ?? '';     $emailTo = $_POST['emailTo'] ?? '';     $emailCc = $_POST['emailCc'] ?? '';     $emailBcc = $_POST['emailBcc'] ?? '';     $emailSubject = $_POST['emailSubject'] ?? '無主題';     $emailMessage = $_POST['emailMessage'] ?? '無內容';      // 從data URI字符串中提取Base64編碼的PDF數據     // datauristring的格式通常是: data:application/pdf;base64,實際數據     // 我們需要移除 "data:application/pdf;base64," 這部分前綴     $pdfData = substr($pdfdoc, strpos($pdfdoc, ',') + 1);      // 對Base64編碼的數據進行解碼     $decodedPdf = base64_decode($pdfData);      // 確保解碼成功且數據不為空     if ($decodedPdf === false || empty($decodedPdf)) {         echo "Error: PDF data decoding failed.";         exit;     }      // 創建PHPMailer實例     $mail = new PHPMailer(true); // 啟用異常處理      try {         // 服務器設置         $mail->SMTPDebug = 0; // 調試輸出 (0 = 關閉, 1 = 客戶端, 2 = 客戶端和服務器)         $mail->isSMTP(); // 使用SMTP         $mail->Host = 'your.smtp.host.com'; // 你的SMTP服務器地址         $mail->SMTPAuth = true; // 啟用SMTP認證         $mail->Username = 'your_smtp_username'; // SMTP 用戶名         $mail->Password = 'your_smtp_password'; // SMTP 密碼         $mail->SMTPSecure = PHPMailer::ENCRYPTION_STARTTLS; // 啟用TLS加密,或者 PHPMailer::ENCRYPTION_SMTPS 用于SSL         $mail->Port = 587; // TLS端口通常是587,SSL通常是465          // 收件人         $companyEmail = 'sender@yourcompany.com'; // 發件人郵箱         $companyName = 'My Company'; // 發件人名稱         $mail->setFrom($companyEmail, $companyName);         $mail->addAddress($emailTo); // 收件人郵箱         if (!empty($emailCc)) {             $mail->addCC($emailCc); // 抄送         }         if (!empty($emailBcc)) {             $mail->addBCC($emailBcc); // 密送         }          // 附件         // AddStringAttachment 允許直接從字符串添加附件         // 參數: $string, $filename, $encoding, $type         $mail->AddStringAttachment($decodedPdf, "GeneratedDocument.pdf", "base64", "application/pdf");          // 內容         $mail->isHTML(true); // 郵件內容為HTML格式         $mail->Subject = $emailSubject; // 郵件主題         $mail->Body    = nl2br(htmlspecialchars($emailMessage)); // 郵件HTML內容         $mail->AltBody = strip_tags($emailMessage); // 非HTML郵件客戶端的替代內容          $mail->send();         echo 'Message has been sent';     } catch (Exception $e) {         echo "Message could not be sent. Mailer Error: {$mail->ErrorInfo}";     } } else {     echo "Invalid request."; } ?>

在 PHP 代碼中,有幾個關鍵點:

  1. 數據提?。?/strong> substr($pdfdoc, strpos($pdfdoc, ‘,’) + 1) 用于從 datauristring 中精確地提取出 Base64 編碼的 PDF 數據,移除了 data:application/pdf;base64, 前綴。
  2. Base64 解碼: base64_decode($pdfData) 將 Base64 編碼的字符串解碼為原始的二進制 PDF 數據。
  3. PHPMailer::AddStringAttachment: 這個方法是 PHPMailer 的一個強大功能,它允許你直接從內存中的字符串(而不是文件路徑)添加附件。參數包括:
    • $string: 解碼后的二進制 PDF 數據。
    • $filename: 附件在郵件中顯示的文件名。
    • $encoding: 附件的編碼方式,這里是 “base64″。
    • $type: 附件的 MIME 類型,這里是 “application/pdf”。

3. 注意事項與總結

  • 異步處理: html2pdf() 是異步的,務必使用 await 或 .then() 確保 PDF 內容完全生成后再進行 Ajax 請求。
  • POST 請求大小限制: Base64 編碼會使數據量增大約 33%。如果 PDF 文件較大,可能會超出 PHP 服務器的 post_max_size 和 upload_max_filesize 限制。你可能需要在 php.ini 中調整這些設置。
  • 安全性: 在處理用戶上傳或生成的數據時,始終要注意安全。雖然 Base64 編碼的 PDF 數據本身通常不包含可執行代碼,但仍需確保你的 PHP 腳本對輸入進行適當的驗證和清理。
  • 錯誤處理: 前端和后端都應包含健壯的錯誤處理機制,以便在出現問題時能夠及時發現并通知用戶。
  • PHPMailer 配置: 請根據你的 SMTP 服務提供商正確配置 PHPMailer 的 Host、Port、Username、Password 和 SMTPSecure 等參數。
  • 文件命名: 在 AddStringAttachment 中指定的文件名 (“GeneratedDocument.pdf”) 是郵件客戶端接收時顯示的文件名,可以根據業務邏輯動態生成。

通過上述步驟,你現在應該能夠成功地在客戶端生成 PDF,并通過 Ajax 將其發送到 PHP 后端,最終使用 PHPMailer 作為附件發送電子郵件。這種方法避免了在服務器端生成 PDF 的額外開銷,同時提供了靈活的客戶端交互體驗。

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

? 版權聲明
THE END
喜歡就支持一下吧
點贊7 分享