PDF生成插件--TcPDF

前言

上星期给毕设网站添加了markdown编辑器,然后周末突然想到如果给编辑器添加一个导出pdf的功能应该挺不错的(话说简书为啥不能导出pdf呢),所以就从网上找了一个生成pdf的PHP插件,叫做 tcpdf,东西很大,连带着实例文件接近16m,花了一天时间去弄这个。

其实这个根据这个插件的实例很快就能弄出pdf来,不过剩下的时间我都在研究怎么能让生成的pdf更好看,很明显我失败了。普通文本还好,如果有这样的代码,要么是显示不出来了,而显示出来的部分也是乱七八糟的。如下:

code显示不正确

code无法显示

虽然对我来说没什么价值,但毕竟研究了一番,写个小日志记录一下吧。

文件引入

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等。而他默认的也是 A4tcpdf支持很多版式,可以到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 页眉页脚设置

包括SetHeaderDatasetFooterDatasetHeaderFontsetFooterFont

SetHeaderData方法有6个参数,包括:

属性 说明 默认值
$ln logo文件路径 ''
$lw logo宽度 0
$ht 页眉标题 ''
$hs 页眉的说明文字 ''
$tc 文本的rgb颜色 array(0,0,0) (黑色)
$lc 页眉下划线的颜色 array(0,0,0) (黑色)

setFooterData只有两个参数,页脚文本颜色和下划线的颜色。

setHeaderFontsetFooterFont分别是设置页眉和页脚的字体,参数只有一个,且注意是数组类型,且传递的数组格式如下:

array(family, style, size)

对应的是font-familyfont-stylefont-size

另外,如果不希望使用页眉页脚,可以使用setPrintHeadersetPrintFooter方法关闭页眉页脚,只要传递参数false即可。

3 文本间距设置

间距包含正文间距和页眉页脚的间距,有三个方法SetMarginsSetHeaderMarginSetFooterMargin

SetMargins是用于正文的,有三个参数,分别表示左侧、上侧、右侧的间距。SetHeaderMarginSetFooterMargin分别是页眉与页脚的间距。

4.设置正文

正文设置包括 分页图片比例正文字体等。

首先利用 SetAutoPageBreak开启分页。该方法传递两个参数,参数1用户启动或禁用自动分页,而参数2只有参数1等于true时才起作用,它定义了页面距底部的距离。

再利用AddPage方法新添分页。同时,该方法如果前面已有页面,该方法会在将页脚添加到页面中 并自动添加下一页,否则直接添加新一页。

字体的设置包括,setFontSubsettingSetFontSetDefaultMonospacedFont

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

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,723评论 6 481
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,485评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 152,998评论 0 344
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,323评论 1 279
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,355评论 5 374
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,079评论 1 285
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,389评论 3 400
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,019评论 0 259
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,519评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,971评论 2 325
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,100评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,738评论 4 324
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,293评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,289评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,517评论 1 262
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,547评论 2 354
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,834评论 2 345

推荐阅读更多精彩内容

  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 134,600评论 18 139
  • Word 2003长篇文档排版技巧(一) 重点总结为两点: 1. 制作长文档前,先要规划好各种设置,尤其是样式设置...
    MrSunbeam阅读 1,977评论 0 12
  • 1. 问:WORD 里边怎样设置每页不同的页眉?如何使不同的章节显示的页眉不同? 答:分节,每节可以设置不同的页眉...
    Jiang锋时刻阅读 5,226评论 4 110
  • 1. 问:WORD 里边怎样设置每页不同的页眉?如何使不同的章节显示的页眉不同? 答:分节,每节可以设置不同的页眉...
    Irinaa阅读 2,833评论 0 43
  • 八月份的时候我和我的好朋友一起去了越南芽庄,是一个海岛,我们在那里感受到了慢生活的节奏 越南人都有一个习惯,早晨四...
    小小小十七阅读 350评论 0 1