做了這麼多年項目,以前隻是在别人的項目中了解過php生成pdf檔案,知道并不難,但是涉及到了pdf開發庫,首先介紹pdf庫。
多種多樣的pdf開發庫
1.WKHTMLTOPDF
wkhtmltopdf是一個很好的解決方案,基本上可以原樣輸出html頁面中的内容,包括:圖檔/代碼高亮部分css/頁頭/頁尾等。有php和指令行方式,大概思路如下:
1) 先擷取所有的遠端html,然後生成wkhtmltopdf的shell腳本
2) 在php中執行此shell腳本檔案批量生成pdf(當然是采用定時任務)
3) 前端頁面中檢查目前頁面是否存在此pdf,如果存在則顯示下載下傳連結
<?php
$domain="http://wiki.eoe.cn";
$htmlUrl=$domain."/show/html/slug/$slug";
$_binpath='/usr/local/bin/';
$_binname='wkhtmltopdf';
$savePath="/User/Xia/eoecn/pdf/";
if(!is_dir($savePath)) {
//需要自己編寫mkdirs函數
@mkdirs($savePath);
}
//由于生成中文目錄會亂碼,這裡過濾掉
if(preg_match("/[x7f-xff]/",$slug)) {
$filename="wiki-slug-$id";
}else{
$filename=$slug;
}
$saveFile=$savePath.$filename.'.pdf';
//判斷是否已經存在
if(file_exists($saveFile)) {
die($saveFile);
}
$header=$domain."/pdf/header";
$command=$_binpath.$_binname
. ' -T 15mm --header-spacing 5 --header-html '.$header
. ' --footer-right "[page]/[toPage]" '.$htmlUrl.' '
. $saveFile;
if($exec) {
exec($command,$output,$var);
}
?>
代碼托管在:
https://code.google.com/p/wkhtmltopdf/
例子:
<?php
require_once('WkHtmlToPdf.php');
$pdf=newWkHtmlToPdf;
// Add a HTML file, a HTML string or a page from a URL
$pdf->addPage('/home/eoe/page.html');
$pdf->addPage('....');
$pdf->addPage('http://google.com');
// Add a cover (same sources as above are possible)
$pdf->addCover('mycover.pdf');
// Add a Table of contents
$pdf->addToc();
// Save the PDF
$pdf->saveAs('/tmp/new.pdf');
// ... or send to client for inline display
$pdf->send();
// ... or send to client as file download
$pdf->send('test.pdf');
2.FPDF
FPDF是一個純粹的通過PHP類來生成PDF文檔的方法,需要生成的内容直接在PHP代碼中來指定,生成文字,圖檔,線條等等,都有自己的方法。不足的是utf8和中文支援很差,分别需要調用chinese-unicode.php和chinese.php等擴充檔案,附上一個簡單的例子:
<?php
require('chinese-unicode.php');
$pdf=newPDF_Unicode();
$pdf->Open();
$pdf->AddPage();
$pdf->AddUniCNShwFont('uni');
$pdf->SetFont('uni','',20);
$pdf->Write(10,"eoe移動開發者社群");
$pdf->Ln();
$pdf->MultiCell (120, 10,"開發者社群");
$pdf->Cell (240, 10,"本文是用utf8編碼格式");
$pdf->Ln();
$pdf->Output();
?>
3.TCPDF
TCPDF是一個用于快速生成PDF檔案的PHP5函數包。TCPDF基于FPDF進行擴充和改進。支援UTF-8,Unicode,HTML和 XHTML。但是檔案很多很大,配置起來比較複雜。相對而言對複雜的css渲染效果不好,而且不能支援html中太多的css檔案,用php轉換效率很慢。 不過官方的文檔很多,例子也很多,也能夠生成很漂亮的pdf檔案。官方網址為:http://www.tcpdf.org/
本人使用的就是這個工具包,是以着重給大家介紹一下,個人認為TCPDF還是很好用的,足以滿足大多數pdf應用,官方提供了豐富的文檔以及例子,各種特性都提供了詳細的例子,上手極快。
以下為TCPDF目錄結構:

本人使用的是CI架構,在将這個庫內建進來的時候,對這個包做了一些改動。
1.所有的基礎配置資訊都在tcpdf根目錄“examples/include/tcpdf_config_alt.php”中,我們為了簡化配置,也使用了它原生的配置檔案,以簡化在開發過程中的配置,将該檔案的内容拷貝至CI架構application/conf/pdf_config.php中,找到“K_PATH_IMAGES”配置項,将其值修改為你項目中圖檔所在的位置,到時候在省城pdf時,所用到的圖檔資源,将從這裡查找。
“PDF_HEADER_LOGO”用于配置pdf中header中logo圖檔,如需要的話設定成你自己的
還有其他一些常用的配置,如配置Top margin、Bottom margin、Left margin、Default main font name
中文問題
使用tcpdf時中文問題是比較常見,在新版的tcpdf中,已經支援中文了,在fonts目錄下有個cid0cs.php和stsonstdlight.php檔案,隻要直接使用即可
$pdf->SetFont('cid0cs','', 10);
$pdf->SetFont('stsongstdlight','', 10);
但是經過本人的實踐,使用這兩種字型,的确是支援中文,但是英文的顯示并不是太好,這種方式生成的PDF檔案的優點是:檔案體積小,生成快速。但也有缺點是,沒有嵌入中文字型,隻限于安裝了Adobe Reader之後才能正常顯示。那萬一使用者使用的是FoxIt Reader或者是Linux作業系統呢?顯示效果就不一樣了。是以,為了保證生成的PDF檔案在任何環境下都有同樣的顯示效果,嵌入字型是必需的。
Windows下有很多中文字型,但是我們要用在TCPDF中的中文字型有下面幾個要求:
· 支援Unicode,因為TCPDF支援的是Unicode;
· 體積越小越好;
· 最好是也支援繁體中文;
将下載下傳後的DroidSansFallback.ttf字型檔案複制到tcpdf目錄下的fonts目錄,并保證web伺服器對該目錄有讀寫的權限,否則在生成tcpdf字型是會出錯。
DroidSansFallback.ttf下載下傳位址
在你的代碼中添加如下代碼:
$fontname=$this->tcpdf->addTTFfont('dist/font/Droid_Sans_Fallback.ttf','TrueTypeUnicode','', 32);
$this->tcpdf->SetFont($fontname,'', 10);
這句代碼将你下載下傳的ttf字型自動轉化為tcpdf使用的字型,将在font目錄下增加這幾個檔案“droid_sans_fallback.ctg.z,droid_sans_fallback.php,droid_sans_fallback.z”,生成之後,以後就可以直接使用這種字型了。
以下為完整的代碼:
//加載配置檔案以及pdf類
require_once(APPPATH .'config/pdf_config.php');
$this->load->library('tcpdf/tcpdf');
// set document information
$this->tcpdf->SetCreator(PDF_CREATOR);
$this->tcpdf->SetAuthor('aaron');
$this->tcpdf->SetTitle($cur_order['title']);
$this->tcpdf->SetSubject('lvpad');
$this->tcpdf->SetKeywords('lvpad, china tour, guide');
// set default header data
$this->tcpdf->SetHeaderData('logo.png', PDF_HEADER_LOGO_WIDTH,'lvpad order','');
// set header and footer fonts
$this->tcpdf->setHeaderFont(Array(PDF_FONT_NAME_MAIN,'', PDF_FONT_SIZE_MAIN));
$this->tcpdf->setFooterFont(Array(PDF_FONT_NAME_DATA,'', PDF_FONT_SIZE_DATA));
// set default monospaced font
$this->tcpdf->SetDefaultMonospacedFont(PDF_FONT_MONOSPACED);
// set margins
$this->tcpdf->SetMargins(PDF_MARGIN_LEFT, PDF_MARGIN_TOP, PDF_MARGIN_RIGHT);
$this->tcpdf->SetHeaderMargin(PDF_MARGIN_HEADER);
$this->tcpdf->SetFooterMargin(PDF_MARGIN_FOOTER);
// set auto page breaks
$this->tcpdf->SetAutoPageBreak(TRUE, PDF_MARGIN_BOTTOM);
// set image scale factor
$this->tcpdf->setImageScale(PDF_IMAGE_SCALE_RATIO);
//set some language-dependent strings (optional)
$l['a_meta_charset'] ='UTF-8';
$l['a_meta_dir'] ='ltr';
$l['a_meta_language'] ='cn';
// TRANSLATIONS --------------------------------------
$l['w_page'] ='page';
$this->tcpdf->setLanguageArray($l);
// 設定字型,如果要支援中文 則選擇支援中文的字型
$fontname=$this->tcpdf->addTTFfont('dist/font/Droid_Sans_Fallback.ttf','TrueTypeUnicode','', 32);
$this->tcpdf->SetFont($fontname,'', 10);
// add a page
$this->tcpdf->AddPage();
$this->tcpdf->setJPEGQuality(75);
// Image example with resizing
$this->tcpdf->Image('images/pdf.jpg', 10, 20, 190, 60,'JPG','http://lvpad.com','', false, 150,'', false, false, 1, false, false, false);
// output the HTML content
$this->tcpdf->writeHTML($html_content, true, false, true, false,'');
// reset pointer to the last page
$this->tcpdf->lastPage();
//Close and output PDF document
$this->tcpdf->Output($cur_order['title'] .'.pdf','I');
生成的pdf就是這樣的:

以上中文問題已經解決,當然,你還可以尋找其他的字型,然後進行嘗試。