使用html2pdf生成PDF并通過Ajax發(fā)送至PHPMailer實現(xiàn)郵件附件功能

使用html2pdf生成PDF并通過Ajax發(fā)送至PHPMailer實現(xiàn)郵件附件功能

本教程詳細(xì)闡述了如何利用前端JavaScripthtml2pdf生成PDF文檔,并將其以Base64編碼字符串的形式通過ajax發(fā)送至后端php腳本。在后端,我們使用PHPMailer庫接收并解碼該P(yáng)DF數(shù)據(jù),最終將其作為附件添加到電子郵件中發(fā)送。文章涵蓋了從客戶端PDF生成、數(shù)據(jù)傳輸?shù)椒?wù)器端數(shù)據(jù)處理和郵件發(fā)送的完整流程,并提供了詳細(xì)的代碼示例和關(guān)鍵注意事項,旨在幫助開發(fā)者高效實現(xiàn)客戶端PDF的服務(wù)器端郵件集成功能。

1. 概述

在web應(yīng)用開發(fā)中,有時我們需要在客戶端生成pdf文檔,并將其作為附件通過電子郵件發(fā)送。直接在客戶端發(fā)送郵件存在安全和功能限制,因此通常的做法是將生成的pdf數(shù)據(jù)發(fā)送到服務(wù)器,再由服務(wù)器端的郵件服務(wù)(如phpmailer)進(jìn)行發(fā)送。本文將詳細(xì)介紹如何結(jié)合html2pdf.JS、ajax和phpmailer實現(xiàn)這一功能。

2. 客戶端PDF生成與數(shù)據(jù)準(zhǔn)備 (JavaScript)

客戶端的核心任務(wù)是將HTML內(nèi)容轉(zhuǎn)換為PDF,并以可傳輸?shù)母袷剑ㄍǔJ荁ase64編碼字符串)獲取PDF數(shù)據(jù)。html2pdf.js庫提供了outputPdf(‘datauristring’)方法來獲取這種格式的數(shù)據(jù)。

2.1 html2pdf配置與PDF生成

首先,確保你的HTML頁面中有一個用于生成PDF的元素,例如一個div。

<div id="printPage">     <!-- 這里是你要轉(zhuǎn)換為PDF的內(nèi)容 -->     <h1>PDF 文檔標(biāo)題</h1>     <p>這是一段示例文本,將被包含在生成的PDF中。</p>     @@##@@ </div> <button id="sendPdfBtn">發(fā)送PDF郵件</button>

接下來,在JavaScript中配置html2pdf并獲取PDF內(nèi)容:

立即學(xué)習(xí)PHP免費(fèi)學(xué)習(xí)筆記(深入)”;

// 假設(shè)你的HTML中有一個ID為'printPage'的元素,這是要轉(zhuǎn)換為PDF的內(nèi)容源 let page = document.getElementById('printPage');  // html2pdf的配置選項 var options = {     margin: [5, 0, 0, 0], // 上右下左邊距     filename: 'document.pdf', // 默認(rèn)文件名,在服務(wù)器端可覆蓋     image: {         type: 'jpeg',         quality: 1 // 圖像質(zhì)量     },     pagebreak: {         mode: ['legacy'] // 分頁模式     },     html2canvas: {         scale: 3 // html2canvas渲染比例,影響清晰度     },     jsPDF: {         unit: 'mm', // 單位         format: 'a4', // 紙張格式         orientation: 'portrait' // 方向:縱向     } };  // 監(jiān)聽按鈕點(diǎn)擊事件,觸發(fā)PDF生成和發(fā)送 $(document).on('click', '#sendPdfBtn', async function() {     let pdfContent;      try {         // 使用await等待PDF內(nèi)容生成,并以datauristring格式獲取         // datauristring格式包含 "data:application/pdf;base64," 前綴         pdfContent = await html2pdf().from(page).set(options).outputPdf('datauristring');          // 成功獲取PDF內(nèi)容后,通過Ajax發(fā)送到服務(wù)器         sendPdfToServer(pdfContent);      } catch (error) {         console.error("PDF生成失敗:", error);         alert("PDF生成失敗,請稍后再試。");     } });  // 這是一個示例函數(shù),用于將PDF內(nèi)容發(fā)送到服務(wù)器 async function sendPdfToServer(pdfData) {     // 假設(shè)ajaxUrl是你的PHP處理腳本的URL     const ajaxUrl = 'your_php_mailer_script.php';       // 其他需要發(fā)送的表單數(shù)據(jù),例如郵件接收者、主題、消息等     const emailTo = $("#emailTo").val(); // 假設(shè)有輸入框獲取收件人     const emailSubject = $("#emailSubject").val(); // 假設(shè)有輸入框獲取郵件主題     const emailMessage = $("#emailMessage").val(); // 假設(shè)有輸入框獲取郵件內(nèi)容      $.ajax({         type: "POST", // 使用POST方法發(fā)送數(shù)據(jù)         url: ajaxUrl,         data: {             action: "sendEmail", // 自定義動作,用于php腳本識別             emailTo: emailTo,             emailSubject: emailSubject,             emailMessage: emailMessage,             pdfContent: pdfData // 將Base64編碼的PDF內(nèi)容作為參數(shù)發(fā)送         },         success: function(response) {             console.log("服務(wù)器響應(yīng):", response);             alert("郵件發(fā)送成功!");         },         error: function(xhr, status, error) {             console.error("Ajax請求失敗:", status, error);             alert("郵件發(fā)送失敗,請檢查網(wǎng)絡(luò)或聯(lián)系管理員。");         }     }); }

關(guān)鍵點(diǎn):

  • outputPdf(‘datauristring’): 這是將PDF內(nèi)容轉(zhuǎn)換為Base64編碼字符串的關(guān)鍵。它返回的字符串會包含一個data:URI前綴,例如data:application/pdf;base64,…。
  • await: html2pdf的outputPdf方法是異步的,因此需要使用await關(guān)鍵字(或.then()方法)來等待PDF內(nèi)容生成完畢。這要求包裹該代碼的函數(shù)是async函數(shù)。
  • Ajax POST請求:通過POST方法發(fā)送數(shù)據(jù),確保PDF內(nèi)容作為請求體的一部分發(fā)送,避免URL長度限制。

3. 服務(wù)器端PDF處理與郵件發(fā)送 (PHP with PHPMailer)

服務(wù)器端PHP腳本負(fù)責(zé)接收客戶端發(fā)送的Base64編碼PDF數(shù)據(jù),解碼它,然后使用PHPMailer將其作為附件發(fā)送。

3.1 接收與解碼PDF數(shù)據(jù)

當(dāng)客戶端通過Ajax發(fā)送pdfContent時,PHP可以通過$_POST[‘pdfContent’]來獲取它。由于datauristring包含data:application/pdf;base64,前綴,我們需要先去除這個前綴,然后再進(jìn)行Base64解碼。

<?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';  // 確保請求是POST并且包含pdfContent if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['pdfContent'])) {     $pdfdoc = $_POST['pdfContent'];      // 移除data URI前綴 "data:application/pdf;base64,"     // strpos(',', $pdfdoc) 找到第一個逗號的位置     $pdfData = substr($pdfdoc, strpos($pdfdoc, ",") + 1); // +1是為了跳過逗號本身      // 對Base64編碼的PDF數(shù)據(jù)進(jìn)行解碼     $decodedPdf = base64_decode($pdfData);      // 獲取其他郵件信息     $emailTo = $_POST['emailTo'] ?? 'default@example.com';     $emailSubject = $_POST['emailSubject'] ?? '來自網(wǎng)站的PDF附件';     $emailMessage = $_POST['emailMessage'] ?? '請查收附件中的PDF文檔。';      // 創(chuàng)建PHPMailer實例     $mail = new PHPMailer(true); // 啟用異常處理      try {         // 服務(wù)器設(shè)置 (根據(jù)你的SMTP服務(wù)商配置)         $mail->SMTPDebug = 0;                      // 啟用詳細(xì)調(diào)試輸出 (0為關(guān)閉,1為客戶端,2為客戶端和服務(wù)器)         $mail->isSMTP();                           // 使用SMTP         $mail->Host       = 'smtp.example.com';    // 你的SMTP服務(wù)器地址         $mail->SMTPAuth   = true;                  // 啟用SMTP認(rèn)證         $mail->Username   = 'your_email@example.com'; // SMTP用戶名         $mail->Password   = 'your_email_password'; // SMTP密碼         $mail->SMTPSecure = PHPMailer::ENCRYPTION_STARTTLS; // 啟用TLS加密,或者PHPMailer::ENCRYPTION_SMTPS for SSL         $mail->Port       = 587;                   // SMTP端口 (TLS通常是587,SSL通常是465)          // 收件人         $mail->setFrom('sender@example.com', '你的公司名稱'); // 發(fā)件人郵箱和名稱         $mail->addAddress($emailTo);               // 添加收件人         // $mail->addCC('cc@example.com');           // 添加抄送         // $mail->addBCC('bcc@example.com');         // 添加密送          // 附件         // AddStringAttachment用于添加字符串作為附件         // 第一個參數(shù)是附件內(nèi)容(已解碼的二進(jìn)制數(shù)據(jù))         // 第二個參數(shù)是附件文件名         // 第三個參數(shù)是內(nèi)容的編碼類型 (這里是'binary'因為我們已經(jīng)解碼了)         // 第四個參數(shù)是MIME類型         $mail->AddStringAttachment($decodedPdf, "GeneratedDocument.pdf", "binary", "application/pdf");          // 內(nèi)容         $mail->isHTML(true);                       // 郵件內(nèi)容為HTML格式         $mail->Subject = $emailSubject;            // 郵件主題         $mail->Body    = $emailMessage;            // 郵件HTML內(nèi)容         $mail->AltBody = strip_tags($emailMessage); // 非HTML郵件客戶端的純文本內(nèi)容          $mail->send();         echo '郵件已成功發(fā)送!';     } catch (Exception $e) {         echo "郵件發(fā)送失敗。 PHPMailer 錯誤: {$mail->ErrorInfo}";     } } else {     echo '無效的請求或缺少PDF內(nèi)容。'; } ?>

關(guān)鍵點(diǎn):

  • Base64解碼: substr($pdfdoc, strpos($pdfdoc, “,”) + 1)用于去除data:application/pdf;base64,前綴。base64_decode()將剩余的Base64字符串轉(zhuǎn)換為原始二進(jìn)制數(shù)據(jù)。
  • AddStringAttachment: PHPMailer的AddStringAttachment()方法非常適合這種場景,因為它允許你直接從字符串添加附件內(nèi)容,而無需先將文件保存到服務(wù)器。
    • 第一個參數(shù)是已解碼的二進(jìn)制PDF數(shù)據(jù)。
    • 第三個參數(shù)”binary”至關(guān)重要,它告訴PHPMailer你提供的數(shù)據(jù)是原始二進(jìn)制格式,而不是需要PHPMailer再次解碼的Base64字符串。
  • PHPMailer配置: 務(wù)必根據(jù)你的SMTP服務(wù)商正確配置Host、Username、Password、SMTPSecure和Port。

4. 注意事項與最佳實踐

  • 文件大小限制: 通過Ajax發(fā)送Base64編碼的PDF數(shù)據(jù),如果PDF文件過大,可能會導(dǎo)致POST請求體過大,超出服務(wù)器或PHP的配置限制(如post_max_size,upload_max_filesize)。對于非常大的PDF文件,考慮將文件上傳到服務(wù)器的臨時目錄,然后將文件路徑傳遞給PHPMailer。
  • 安全性:
    • 輸入驗證: 永遠(yuǎn)不要信任來自客戶端的數(shù)據(jù)。對emailTo、emailSubject、emailMessage等所有接收到的POST數(shù)據(jù)進(jìn)行嚴(yán)格的驗證和過濾,以防止xss攻擊、郵件頭注入等安全漏洞。
    • 文件類型驗證: 雖然這里是內(nèi)部生成,但如果是用戶上傳,應(yīng)嚴(yán)格驗證文件類型。
  • 錯誤處理:
    • 客戶端: 在JavaScript中添加try…catch塊來捕獲html2pdf生成PDF時的錯誤,以及Ajax請求的錯誤。
    • 服務(wù)器端: PHPMailer的構(gòu)造函數(shù)傳入true可以啟用異常處理,try…catch塊可以捕獲郵件發(fā)送過程中的錯誤,并通過$mail->ErrorInfo獲取詳細(xì)錯誤信息。
  • 異步操作: html2pdf的PDF生成和Ajax請求都是異步操作。確保你的JavaScript代碼正確處理了這些異步性(使用async/await或.then())。
  • PHPMailer庫路徑: 在PHP代碼中,確保require語句指向了PHPMailer庫的正確路徑。

5. 總結(jié)

通過結(jié)合html2pdf.js在客戶端生成PDF,利用Ajax將Base64編碼的PDF數(shù)據(jù)傳輸?shù)椒?wù)器,再通過PHPMailer在服務(wù)器端解碼并發(fā)送郵件附件,我們實現(xiàn)了一個完整的客戶端PDF生成與服務(wù)器端郵件發(fā)送的解決方案。這種方法避免了在客戶端直接處理郵件發(fā)送的復(fù)雜性和安全問題,提供了一個健壯且可擴(kuò)展的實現(xiàn)方案。

使用html2pdf生成PDF并通過Ajax發(fā)送至PHPMailer實現(xiàn)郵件附件功能

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

? 版權(quán)聲明
THE END
喜歡就支持一下吧
點(diǎn)贊14 分享