แปลง html เป็น pdf รองรับภาษาไทย ด้วย mPdf และ codeigniter
แปลง html เป็น pdf รองรับภาษาไทย ด้วย mPdf และ codeigniter
ในการพัฒนา web application อีกหนึ่งโจทย์สำคัญที่เรามักจะได้รับจากลูกค้าคือการทำรายงานข้อมูลในรูปแบบไฟล์ PDF บางเว็บไซต์ อาจจะต้องนำออกข้อมูลทั้งในส่วน Back-End และ Front-End และปัญหาที่เรามักจะพบเจออยู่บ่อย ๆ คือการจัดการกับรูปแบบไฟล์ pdf ที่เป็น Dynamic Content เนื้อหาภายในมีการปรับปรุงเปลี่ยนแปลงอยู่เรื่อย ๆ เช่น การออกใบหักภาษี ณ ที่จ่าย การออกใบเสร็จรับเงิน เป็นต้น
ปัญหาที่มักจะเจอในการ export pdf คือการจัดการกับภาษาไทย หรือการจัดตำแหน่งฟอนต์ที่มักจะไม่ตรงกับตำแหน่งตามที่ออกแบบไว้ เมื่อ export เป็น pdf ไฟล์ โดยหลัก ๆ ในบทความนี้เราจะใช้ความสามารถของ mPDf ซึ่งเป็น php library ที่ถูกพัฒนาขึ้นมาเพื่อ generate PDF file โดยเฉพาะ
สิ่งที่ต้องใช้สำหรับบทความนี้
- mPDF PHP Library https://github.com/mpdf/mpdf
- PHP Codeigniter Framework https://codeigniter.com
- html2canvas.js https://html2canvas.hertzen.com
- jQuery Javascript Library https://jquery.com
ดาวน์โหลดและติดตั้ง mPDf
- 1. เริ่มต้นให้ไปดาวน์โหลด mPDF library ที่ github ตามลิงค์นี้ครับ https://github.com/mpdf/mpdf
- 2. หลังจากดาวน์โหลดเสร็จแล้วเราจะได้โฟลเด้อชื่อว่า mpdf ให้นำไปวางไว้ใน application/third_party จากนั้นให้สร้างโฟลเด้อตั้งชื่อว่า download กำหนด permission เป็น 777 สำหรับบันทึกไฟล์ image และ pdf
- 3. จากนั้นให้สร้าง Controller ขึ้นมา ตั้งชื่อว่า Pdf.php ให้ include mPdf เข้ามาใช้งานดังนี้
class Pdf extends CI_Controller { public function __construct() { parent::__construct(); $this->load->helper(array('url')); include(APPPATH."third_party/mpdf/mpdf.php"); }
- 4. จากนั้นให้สร้าง view ที่เราต้องการจะแปลงเป็น pdf ขึ้นมา ในที่นี้ผู้เขียนต้องการจะ export ใบเสร็จรับเงิน จึงตั้งชื่อไฟล์ว่า receipt_view.php และในไฟล์นี้ได้เขียน html สำหรับแสดงรูปแบบใบเสร็จดังนี้
ให้สังเกตุว่าในส่วนของ element section จะมีการกำหนดไอดีและตั้งชื่อว่า pdf หมายความว่าข้อมูลที่อยู่ใน section นี้ทั้งหมดจะถูกนำออกในรูปแบบ pdf file
<section class="sheet padding-20mm" id="pdf"> <h1>บริษัท โค๊ดบี จำกัด</h1> <ul> <li>41/94 ถนนแจ้งวัฒนา ปากเกร็ด นนทบุรี 11120</li> <li>โทร. +66 085.900.3405</li> <li>เว็บไซต์ : www.codebee.co.th</li> </ul> <article> <h2>from:</h2> <p>บริษัท โค๊ดบี จำกัด</p> <h3>For:</h3> <p>บริษัท แฮปปี้ แคท เฮ้า จำกัด</p> <h4>1,000THB</h4> <ul> <li>Tax: included</li> <li>Paid by: cash</li> <li>No. 00001</li> <li>Oct 10, 2017</li> </ul> </article> </section>
ตัวอย่างการแสดงผลเมื่อดูผ่าน browser
- 5. วิธีที่ง่ายที่สุดในการจัดการให้การแสดงผลของ pdf ไม่ผิดเพี้ยนไปจาก html ที่เราออกแบบไว้ คือการแปลง html ให้เป็นรูปภาพก่อน ให้ใช้ความสามารถของ html2canvas.js แปลง html ตั้งแต่ไอดี pdf ให้เป็นรูปก่อน สามารถเขียนคำสั่งได้ดังนี้
var baseURL = "<?php echo base_url(); ?>"; function downloadPDF($pdf_id){ $("#"+$pdf_id).css({ opacity: 1 }); html2canvas([document.getElementById($pdf_id)], { onrendered: function(canvas) { var image = canvas.toDataURL('image/png'); SaveImage(image); } }); }
- 6. หลังจากได้รูปภาพแบบ base64 แล้วให้เขียนคำสั่งส่งข้อมูลไปที่ Pdf Controller เพื่อบันทึกรูปและแปลงเป็น PDf ตามลำดัง
function SaveImage(image){ $.ajax({ type: 'POST', url: baseURL+'pdf/save', data: {base64Image:image,image_name:"pdf"}, success: function(image) { var d = new Date(); var n = d.getTime(); window.location = image+"?t="+n; } }); }
- 7. ใน Pdf Controller ให้เขียนคำสั่งเพื่อบันทึกรูปและแปลงเป็น pdf ด้วย mPdf ดังนี้
public function save() { // แปลง html view ให้เป็นรูปก่อน $base64Image = $_REQUEST['base64Image']; $image_name = $this->input->post('image_name'); $image_name_save = $image_name.".png"; file_put_contents(FCPATH."download/".$image_name_save, base64_decode(str_replace('data:image/png;base64,','',$base64Image))); // นำรูปมา save เป็น pdf ด้วย mPDf $image = base_url("download/".$image_name_save); $html = '<img src="'.$image.'"/>'; $mpdf=new mPDF('c'); $mpdf->WriteHTML($html); $pdf_name = $image_name.".pdf"; $mpdf->Output(FCPATH."download/".$pdf_name,"F"); //F echo base_url("download/".$pdf_name); }
- 8. ที่ไฟล์ receipt_view ให้เรียกใช้งานฟังก์ชั่นสำหรับดาวน์โหลดด pdf ดังนี้
$(document).ready(function(){ setTimeout(init, 1000); }); function init(){ downloadPDF("pdf"); }
- 9. ทดสอบการทำงาน โดยการ load receipt_view ที่ index ของ pdf controller ดังนี้
public function index(){ $this->load->view("receipt_view"); }