前言
上星期給畢設(shè)網(wǎng)站添加了markdown編輯器,然后周末突然想到如果給編輯器添加一個導出pdf的功能應該挺不錯的(話說簡書為啥不能導出pdf呢),所以就從網(wǎng)上找了一個生成pdf的PHP插件,叫做 tcpdf,東西很大,連帶著實例文件接近16m,花了一天時間去弄這個。
其實這個根據(jù)這個插件的實例很快就能弄出pdf來,不過剩下的時間我都在研究怎么能讓生成的pdf更好看,很明顯我失敗了。普通文本還好,如果有這樣的代碼,要么是顯示不出來了,而顯示出來的部分也是亂七八糟的。如下:


雖然對我來說沒什么價值,但畢竟研究了一番,寫個小日志記錄一下吧。
文件引入
從 TCPDF下載最新的版本,雖然下載包中附帶了65個demo,但它沒告訴我哪些文檔是必須引入的。那我們直接來看程序文件。打開主程序文件tcpdf.php,從開始的代碼可以看出,以下文件必須被包含:
tcpdf_autoconfig.php
include文件夾
在搜索所有文件中的require_once,有如下文件:
tcpdf_barcodes_1d.php
tcpdf_barcodes_2d.php
ok,將tcpdf.php和上述文件復制到項目文件夾,
require_once('./tcpdf.php');
$pdf = new TCPDF();
執(zhí)行,然后就出錯了:
Warning: opendir(C:\Practice\Apache24\htdocs\demo\PDF/fonts/,C:\Practice\Apache24\htdocs\demo\PDF/fonts/): in C:\Practice\Apache24\htdocs\demo\PDF\tcpdf.php on line 4148
Warning: opendir(C:\Practice\Apache24\htdocs\demo\PDF/fonts/): failed to open dir: No such file or directory in C:\Practice\Apache24\htdocs\demo\PDF\tcpdf.php on line 4148
TCPDF ERROR: Could not include font definition file: helvetica
顯然還要將下載包中的fonts文件夾復制到項目中。
執(zhí)行
經(jīng)過上面的引入和調(diào)試,現(xiàn)在能正常實例化了,在上面代碼中我實例化tcpdf方法未傳遞任何參數(shù),但實際上該方法有7個參數(shù)可傳遞,如下:
| 屬性 | 說明 | 默認值 |
|---|---|---|
| $orientation | 設(shè)置pdf頁面的方向 | Portrait |
| $unit | 設(shè)置pdf單元的測量單位 | mm |
| $format | 頁面的版式 | A4 |
| $unicode | 是否使用unicode | true |
| $encoding | 字符編碼 | utf-8 |
| $diskcache | 該功能被廢棄 | false |
| $pdfa | 啟用/關(guān)閉pdf/a | true |
具體說明如下:
$orientation
用來設(shè)置pdf頁面的方向,有兩個參數(shù):
| 參數(shù)名 | 含義 | 默認 |
|---|---|---|
| P/Portrait | 縱向 | true |
| L/Landscape | 橫向 | false |
$unit
用來設(shè)置pdf單元的測量單位,有四個參數(shù)
| 參數(shù)名 | 含義 | 默認 |
|---|---|---|
| pt: point | 點數(shù) | false |
| mm: millimeter | 毫米 | true |
| cm: centimeter | 厘米 | false |
| in: inch | 英寸 | false |
$format
表示頁面的版式,如 A4等。而他默認的也是 A4。 tcpdf支持很多版式,可以到tcpdf_static.php中的$page_formats屬性中查看。
$unicode
布爾類型,true代表是輸入文本是$unicode。這個沒什么說的,一般都是unicode,默認為true就行。
$encoding
字符編碼,默認是utf-8。
$diskcache
這個參數(shù)官網(wǎng)沒多做解釋,程序文件也是,不過在其中寫了DEPRECATED FEATURE,顯然該功能被廢棄了,不建議使用,直接設(shè)置為false即可。
$pdfa
PDF/A是PDF 的 ISO 標準,它是為長期保存文件而設(shè)計的,屏蔽了一些編輯功能。即設(shè)置`$pdfa = true**的話,生成的pdf是不能夠編輯的。
好了,弄清楚了這7個參數(shù),可以實例化了,當然如果你只是簡單的使用一下可以直接進行實例化,因為這7個參數(shù)都有默認值,而一般這些默認值不用修改。
配置
tcpdf的配置選項很多,大致分成4個部分,包括文檔的信息設(shè)置,頁眉頁腳設(shè)置,文本間距設(shè)置,正文設(shè)置。其中分成若干小部分。在完成功能之前,簡單介紹一下,這幾部分必要的方法。
如下:
1 文檔的信息設(shè)置
包括 SetCreator(文檔創(chuàng)建者名稱),SetAuthor(設(shè)置作者),SetTitle(設(shè)置文檔標題),SetKeywords(文檔關(guān)鍵詞)。這幾個方法的參數(shù)沒什么可說的,string類型,主要就是用來設(shè)置文檔的屬性的,如下面的東西一樣:

2 頁眉頁腳設(shè)置
包括SetHeaderData,setFooterData,setHeaderFont,setFooterFont
SetHeaderData方法有6個參數(shù),包括:
| 屬性 | 說明 | 默認值 |
|---|---|---|
| $ln | logo文件路徑 | '' |
| $lw | logo寬度 | 0 |
| $ht | 頁眉標題 | '' |
| $hs | 頁眉的說明文字 | '' |
| $tc | 文本的rgb顏色 | array(0,0,0) (黑色) |
| $lc | 頁眉下劃線的顏色 | array(0,0,0) (黑色) |
而setFooterData只有兩個參數(shù),頁腳文本顏色和下劃線的顏色。
而setHeaderFont,setFooterFont分別是設(shè)置頁眉和頁腳的字體,參數(shù)只有一個,且注意是數(shù)組類型,且傳遞的數(shù)組格式如下:
array(family, style, size)
對應的是font-family,font-style,font-size。
另外,如果不希望使用頁眉頁腳,可以使用setPrintHeader和setPrintFooter方法關(guān)閉頁眉頁腳,只要傳遞參數(shù)false即可。
3 文本間距設(shè)置
間距包含正文間距和頁眉頁腳的間距,有三個方法SetMargins,SetHeaderMargin,SetFooterMargin。
SetMargins是用于正文的,有三個參數(shù),分別表示左側(cè)、上側(cè)、右側(cè)的間距。SetHeaderMargin和SetFooterMargin分別是頁眉與頁腳的間距。
4.設(shè)置正文
正文設(shè)置包括 分頁,圖片比例,正文字體等。
首先利用 SetAutoPageBreak開啟分頁。該方法傳遞兩個參數(shù),參數(shù)1用戶啟動或禁用自動分頁,而參數(shù)2只有參數(shù)1等于true時才起作用,它定義了頁面距底部的距離。
再利用AddPage方法新添分頁。同時,該方法如果前面已有頁面,該方法會在將頁腳添加到頁面中 并自動添加下一頁,否則直接添加新一頁。
字體的設(shè)置包括,setFontSubsetting、SetFont、SetDefaultMonospacedFont。
setFontSubsetting這個方法我沒弄懂,因為不了解什么叫字體構(gòu)造子集,跳過。SetFont就是用來設(shè)置正文字體,參數(shù)傳遞和setHeaderFont類似,但該方法將三個選項分成了三個參數(shù)傳遞,而不是傳遞數(shù)組。另外,如果是生成中文pdf需要尤其注意,必須設(shè)置字體為stsongstdlight,否則會出現(xiàn)中文亂碼。
當然還有正文寫入了,如果只是普通文檔,一般使用Write方法,共有12個參數(shù),所以我就不一一介紹了,說一下必填的兩個參數(shù),也就是前兩個參數(shù),$h表示行高,$txt表示要打印的內(nèi)容。其他可以默認。
如果打印html文檔且包含了css文件,就需要使用writeHTML方法,該方法有6個參數(shù),但必填的只有一個就是需要打印的內(nèi)容,其他的參數(shù)可以是默認值。
好了,配置、參數(shù)介紹完畢,按照我介紹的步驟一步步的來,就能生成pdf了,下面是我自己寫的生成代碼:
class pdf {
# 常量設(shè)置
const PDF_LOGO = '\Logo\logo_big.png'; // LOGO路徑 該路徑是tcpdf下
const PDF_LOGO_WIDTH = '20'; // LOGO寬度
const PDF_TITLE = 'www.liuweime.me'; //
const PDF_HEAD = '上電腦課';
const PDF_FONT = 'stsongstdlight';
const PDF_FONT_STYLE = '';
const PDF_FONT_SIZE = 10;
const PDF_FONT_MONOSPACED = 'courier';
const PDF_IMAGE_SCALE='1.25';
# tcpdf對象存儲
protected $pdf = null;
/**
* 構(gòu)造函數(shù) 引入插件并實例化
*/
public function __construct() {
# 實例化該插件
$this->pdf = new TCPDF();
}
/**
* 設(shè)置文檔信息
* @param $user string 文檔作者
* @param $title string 文檔標題
* @param $subject string 文檔主題
* @param $keywords string 文檔關(guān)鍵字
* @return null
*/
protected function setDocumentInfo($user = '', $title = '', $subject ='', $keywords = '') {
if(empty($user) || empty($title)) return false;
# 文檔創(chuàng)建者名稱
$this->pdf->SetCreator(APP_NAME);
# 作者
$this->pdf->SetAuthor($user);
# 文檔標題
$this->pdf->SetTitle($title);
# 文檔主題
if(!empty($subject)) $this->pdf->SetSubject($subject);
# 文檔關(guān)鍵字
if(!empty($keywords)) $this->pdf->SetKeywords($keywords);
}
/**
* 設(shè)置文檔的頁眉頁腳信息
* @param null
* @return null
*/
protected function setHeaderFooter() {
# 設(shè)置頁眉信息
# 格式 logo地址 logo寬度 頁眉標題 頁眉說明文字 頁眉字體顏色 頁眉下劃線顏色
$this->pdf->SetHeaderData(self::PDF_LOGO , self::PDF_LOGO_WIDTH , self::PDF_TITLE , self::PDF_HEAD , array(35 , 35 , 35) , array(221,221,221));
# 設(shè)置頁腳信息
# 格式 頁腳字體顏色 頁腳下劃線顏色
$this->pdf->setFooterData(array(35 , 35 , 35) , array(221,221,221));
# 設(shè)置頁眉頁腳字體
$this->pdf->setHeaderFont(array('stsongstdlight' , self::PDF_FONT_STYLE , self::PDF_FONT_SIZE));
$this->pdf->setFooterFont(array('helvetica' , self::PDF_FONT_STYLE , self::PDF_FONT_SIZE));
}
/**
* 關(guān)閉頁眉頁腳
* @param null
* @return null
*/
protected function closeHeaderFooter() {
# 關(guān)閉頁頭
$this->pdf->setPrintHeader(false);
# 關(guān)閉頁腳
$this->pdf->setPrintFooter(false);
}
/**
* 設(shè)置間距 包括正文間距 頁眉頁腳間距
* @param null
* @return null
*/
protected function setMargin() {
# 設(shè)置默認的等寬字體
$this->pdf->SetDefaultMonospacedFont('courier');
# 正文左側(cè) 上側(cè) 右側(cè)間距
$this->pdf->SetMargins(15, 7, 15);
# 頁眉間距
$this->pdf->SetHeaderMargin(5);
# 頁腳間距
$this->pdf->SetFooterMargin(10);
}
/**
* 正文設(shè)置 包括 分頁 圖片比例 正文字體
* @param null
* @return null
*/
protected function setMainBody() {
# 開啟分頁 true開啟 false關(guān)閉 開啟分頁時參數(shù)2起作用 表示正文距底部的間距
$this->pdf->SetAutoPageBreak(true , 25);
# 設(shè)置圖片比例
$this->pdf->setImageScale(self::PDF_IMAGE_SCALE);
#
$this->pdf->setFontSubsetting(true);
# 設(shè)置正文字體 stsongstdlight是Adobe Reader默認字體
> $this->pdf->SetFont('stsongstdlight', '', 14);
# 添加頁面 該方法如果前面已有頁面 會在將頁腳添加到頁面中 并自動添加下一頁 否則添加新一頁
$this->pdf->AddPage();
}
/**
* 生成pdf
* @param $info array
* array(
* 'user'=>'文檔作者' ,
* 'title'=>'文檔標題' ,
* 'subject'=>'文檔主題' ,
* 'keywords'=>'文檔關(guān)鍵字' ,
* 'content'=>'文檔正文內(nèi)容' ,
* 'HT'=>'是否開啟頁眉頁腳' ,
* 'path'=>'文檔保存路徑');
* @return null
*/
public function createPDF($info = array()) {
if(empty($info) || !is_array($info)) return false;
$this->setDocumentInfo($info['user'] , $info['title'] , $info['subject'] , $info['keywords']);
if(!$info['HT']) {
$this->closeHeaderFooter();
} else {
$this->setHeaderFooter();
}
$this->setMargin();
$this->setMainBody();
# 寫入內(nèi)容
$this->pdf->writeHTML($info['content'], true, false, true, false, '');
# 輸出 I輸出到瀏覽器 F輸出到指定路徑
$this->pdf->Output($info['path'] , 'F');
}
}
結(jié)語
雖然,沒達到我預想的效果,但還是有收獲的,而且我是第一次看到兩萬多行代碼在一個文件中的PHP文件,有點66的,本來準備看看源碼,學習學習的,看到代碼后有點發(fā)虛,哈哈。
END