前言
上星期给毕设网站添加了markdown编辑器,然后周末突然想到如果给编辑器添加一个导出pdf的功能应该挺不错的(话说简书为啥不能导出pdf呢),所以就从网上找了一个生成pdf的PHP插件,叫做 tcpdf,东西很大,连带着实例文件接近16m,花了一天时间去弄这个。
其实这个根据这个插件的实例很快就能弄出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();
执行,然后就出错了:
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文件夹复制到项目中。
执行
经过上面的引入和调试,现在能正常实例化了,在上面代码中我实例化tcpdf
方法未传递任何参数,但实际上该方法有7个参数可传递,如下:
属性 | 说明 | 默认值 |
---|---|---|
$orientation | 设置pdf页面的方向 | Portrait |
$unit | 设置pdf单元的测量单位 | mm |
$format | 页面的版式 | A4 |
$unicode | 是否使用unicode | true |
$encoding | 字符编码 | utf-8 |
$diskcache | 该功能被废弃 | false |
$pdfa | 启用/关闭pdf/a | true |
具体说明如下:
$orientation
用来设置pdf页面的方向,有两个参数:
参数名 | 含义 | 默认 |
---|---|---|
P/Portrait | 纵向 | true |
L/Landscape | 横向 | false |
$unit
用来设置pdf单元的测量单位,有四个参数
参数名 | 含义 | 默认 |
---|---|---|
pt: point | 点数 | 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
这个参数官网没多做解释,程序文件也是,不过在其中写了DEPRECATED FEATURE
,显然该功能被废弃了,不建议使用,直接设置为false
即可。
$pdfa
PDF/A是PDF 的 ISO 标准,它是为长期保存文件而设计的,屏蔽了一些编辑功能。即设置`$pdfa = true**的话,生成的pdf是不能够编辑的。
好了,弄清楚了这7个参数,可以实例化了,当然如果你只是简单的使用一下可以直接进行实例化,因为这7个参数都有默认值,而一般这些默认值不用修改。
配置
tcpdf的配置选项很多,大致分成4个部分,包括文档的信息设置,页眉页脚设置,文本间距设置,正文设置。其中分成若干小部分。在完成功能之前,简单介绍一下,这几部分必要的方法。
如下:
1 文档的信息设置
包括 SetCreator(文档创建者名称)
,SetAuthor(设置作者)
,SetTitle(设置文档标题)
,SetKeywords(文档关键词)
。这几个方法的参数没什么可说的,string类型,主要就是用来设置文档的属性的,如下面的东西一样:
2 页眉页脚设置
包括SetHeaderData
,setFooterData
,setHeaderFont
,setFooterFont
SetHeaderData
方法有6个参数,包括:
属性 | 说明 | 默认值 |
---|---|---|
$ln | logo文件路径 | '' |
$lw | logo宽度 | 0 |
$ht | 页眉标题 | '' |
$hs | 页眉的说明文字 | '' |
$tc | 文本的rgb颜色 | array(0,0,0) (黑色) |
$lc | 页眉下划线的颜色 | array(0,0,0) (黑色) |
而setFooterData
只有两个参数,页脚文本颜色和下划线的颜色。
而setHeaderFont
,setFooterFont
分别是设置页眉和页脚的字体,参数只有一个,且注意是数组类型,且传递的数组格式如下:
array(family, style, size)
对应的是font-family
,font-style
,font-size
。
另外,如果不希望使用页眉页脚,可以使用setPrintHeader
和setPrintFooter
方法关闭页眉页脚,只要传递参数false
即可。
3 文本间距设置
间距包含正文间距和页眉页脚的间距,有三个方法SetMargins
,SetHeaderMargin
,SetFooterMargin
。
SetMargins
是用于正文的,有三个参数,分别表示左侧、上侧、右侧的间距。SetHeaderMargin
和SetFooterMargin
分别是页眉与页脚的间距。
4.设置正文
正文设置包括 分页,图片比例,正文字体等。
首先利用 SetAutoPageBreak
开启分页。该方法传递两个参数,参数1用户启动或禁用自动分页,而参数2只有参数1等于true时才起作用,它定义了页面距底部的距离。
再利用AddPage
方法新添分页。同时,该方法如果前面已有页面,该方法会在将页脚添加到页面中 并自动添加下一页,否则直接添加新一页。
字体的设置包括,setFontSubsetting
、SetFont
、SetDefaultMonospacedFont
。
setFontSubsetting
这个方法我没弄懂,因为不了解什么叫字体构造子集,跳过。SetFont
就是用来设置正文字体,参数传递和setHeaderFont
类似,但该方法将三个选项分成了三个参数传递,而不是传递数组。另外,如果是生成中文pdf需要尤其注意,必须设置字体为stsongstdlight
,否则会出现中文乱码。
当然还有正文写入了,如果只是普通文档,一般使用Write
方法,共有12个参数,所以我就不一一介绍了,说一下必填的两个参数,也就是前两个参数,$h
表示行高,$txt
表示要打印的内容。其他可以默认。
如果打印html文档且包含了css文件,就需要使用writeHTML
方法,该方法有6个参数,但必填的只有一个就是需要打印的内容,其他的参数可以是默认值。
好了,配置、参数介绍完毕,按照我介绍的步骤一步步的来,就能生成pdf了,下面是我自己写的生成代码:
class pdf {
# 常量设置
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;
/**
* 构造函数 引入插件并实例化
*/
public function __construct() {
# 实例化该插件
$this->pdf = new TCPDF();
}
/**
* 设置文档信息
* @param $user string 文档作者
* @param $title string 文档标题
* @param $subject string 文档主题
* @param $keywords string 文档关键字
* @return null
*/
protected function setDocumentInfo($user = '', $title = '', $subject ='', $keywords = '') {
if(empty($user) || empty($title)) return false;
# 文档创建者名称
$this->pdf->SetCreator(APP_NAME);
# 作者
$this->pdf->SetAuthor($user);
# 文档标题
$this->pdf->SetTitle($title);
# 文档主题
if(!empty($subject)) $this->pdf->SetSubject($subject);
# 文档关键字
if(!empty($keywords)) $this->pdf->SetKeywords($keywords);
}
/**
* 设置文档的页眉页脚信息
* @param null
* @return null
*/
protected function setHeaderFooter() {
# 设置页眉信息
# 格式 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));
# 设置页脚信息
# 格式 页脚字体颜色 页脚下划线颜色
$this->pdf->setFooterData(array(35 , 35 , 35) , array(221,221,221));
# 设置页眉页脚字体
$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));
}
/**
* 关闭页眉页脚
* @param null
* @return null
*/
protected function closeHeaderFooter() {
# 关闭页头
$this->pdf->setPrintHeader(false);
# 关闭页脚
$this->pdf->setPrintFooter(false);
}
/**
* 设置间距 包括正文间距 页眉页脚间距
* @param null
* @return null
*/
protected function setMargin() {
# 设置默认的等宽字体
$this->pdf->SetDefaultMonospacedFont('courier');
# 正文左侧 上侧 右侧间距
$this->pdf->SetMargins(15, 7, 15);
# 页眉间距
$this->pdf->SetHeaderMargin(5);
# 页脚间距
$this->pdf->SetFooterMargin(10);
}
/**
* 正文设置 包括 分页 图片比例 正文字体
* @param null
* @return null
*/
protected function setMainBody() {
# 开启分页 true开启 false关闭 开启分页时参数2起作用 表示正文距底部的间距
$this->pdf->SetAutoPageBreak(true , 25);
# 设置图片比例
$this->pdf->setImageScale(self::PDF_IMAGE_SCALE);
#
$this->pdf->setFontSubsetting(true);
# 设置正文字体 stsongstdlight是Adobe Reader默认字体
> $this->pdf->SetFont('stsongstdlight', '', 14);
# 添加页面 该方法如果前面已有页面 会在将页脚添加到页面中 并自动添加下一页 否则添加新一页
$this->pdf->AddPage();
}
/**
* 生成pdf
* @param $info array
* array(
* 'user'=>'文档作者' ,
* 'title'=>'文档标题' ,
* 'subject'=>'文档主题' ,
* 'keywords'=>'文档关键字' ,
* 'content'=>'文档正文内容' ,
* '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();
# 写入内容
$this->pdf->writeHTML($info['content'], true, false, true, false, '');
# 输出 I输出到浏览器 F输出到指定路径
$this->pdf->Output($info['path'] , 'F');
}
}
结语
虽然,没达到我预想的效果,但还是有收获的,而且我是第一次看到两万多行代码在一个文件中的PHP文件,有点66的,本来准备看看源码,学习学习的,看到代码后有点发虚,哈哈。
END