PHP制作pdf文档方法

时间:2024-02-19 15:08:26

  本篇博客是在看完 php+mysql web书以后自己的测试代码,虽然是测试代码,但不是简单的粘贴复制,为了学习thinkPHP框架,自己就用这个来做的,而且这本书已经有年头了。原书的代码中的方法,在查阅手册的时候,很多都已经弃用了,所以分享给大家还是有必要的。php制作pdf文档的方法有很多,我写的只是其中一种,大家有时间可以多看看。好了,进入正题

  准备工作:

    1、php手册(在线php关于pdf地址: http://php.net/manual/zh/intro.pdf.php )

    2、PDFlib(http://www.pdflib.com/download/pdflib-family/pdflib-9/ 下载)

  开始安装PDFlib扩展

    第一步,下载最新的pdflib扩展,

    我下载下来后里面有很多东西

    

    

    

    

    我的php版本是PHP Version 5.2.17所以我选的是php_520里面的文件,将里面的文件名称改成libpdf_php.dll =》php_pdf.dll

    第二步安装

      将php_pdf.dll文件放到php的ext目录

         打开php.ini文件将里面extension=php_pdf.dll去掉分号(如果没有,就添加上这一行),如果没有找到添加即可。

      第三步重启apache或IIS

    

  建立项目pdfApp

    这里我为了学习thinkPHP,所以使用的是thinkPHP框架,我们的目标是根据用户的答题情况->作出成绩判断->生成用户的pdf成绩证书

    由于项目比较小,我们简单使用一个控制器就可以完成,代码就不分开贴了,最下面有完整的IndexController代码

    首先,进入index方法显示信息搜集页面(就是controller中的index方法)

    

    

    进入根据选择跳转到score方法

    

 

    生成PDF证书

    下面的一页就是代码中测试制作第二页的输出

    怎么会有这么大的水印啊,影响美观。请不要相信那个大大的水印是我加的

    由于PDFlib并不是开源免费的,所以、、、、、

    

 

    

  完整代码:

    需要注意的是:

    PDFlib的使用也是有两种:面向对象和面向过程

    区别是:对于手册中的所有方法都是面向过程的方法,在使用面向对象时,只需要把前面的前缀\'PDF_\'用对象调用替换即可,

    同时忽略方法中的\'resource $pdfdoc\' 参数

    

  1 <?php
  2 namespace Home\Controller;
  3 use Think\Controller;
  4 class IndexController extends Controller {
  5     public function index(){
  6         $this->display();
  7     }
  8     public function score() {
  9         $name = I(\'post.name\');
 10         $question_1 = I(\'post.q1\');
 11         $question_2 = I(\'post.q2\');
 12         $question_3 = I(\'post.q3\');
 13         
 14         if ( (\'\' == $question_1) || (\'\' == $question_2) || (\'\' == $question_3) || (\'\' == $name)) {
 15             # code...
 16             $err_url = U(\'Index/index\');
 17             $this->assign(\'url\',$err_url);
 18             $this->display(\'nullError\');
 19         }else {
 20             $score = 0;
 21             1 == $question_1 && $score++;
 22             1 == $question_2 && $score++;
 23             1 == $question_3 && $score++;
 24 
 25             //convert score to a percentage
 26             $score = $score / 3 * 100;
 27 
 28             if($score < 50) {
 29               // this person failed
 30                 $this->display(\'notPass\');
 31               
 32             }  else {
 33               // create a string containing the score to one decimal place
 34               $score = number_format($score, 1);
 35               $this->assign(\'name\',$name);
 36               $this->assign(\'score\',$score);
 37               $this->display(\'isPass\');
 38             }
 39         }
 40     }
 41     public function pdflib() {
 42         $name = I(\'post.name\');
 43         $score = I(\'post.score\');
 44         if(!$name || !$score) {
 45             echo \'name and score is null\';
 46         }else {
 47             // 开始制作pdf文档
 48             // 注意:PDFlib的使用也是有两种:面向对象和面向过程
 49             // 区别是:对于手册中的所有方法都是面向过程的方法,在使用面向对象时,只需要把前面的前缀\'PDF_\'用对象调用替换即可,
 50             // 同时忽略方法中的\'resource $pdfdoc\' 参数
 51             // 例如我们可以创建一个pdf对象  $pdf = new \PDFlib();
 52             // 也可以使用 $pdf = pdf_new();创建一个pdf资源句柄
 53             try {
 54                 $date = date(\'F d, Y\');  // 获取系统当前时间
 55                 //  实例化一个PDFlib对象,注意我们的PDFlib由于是在php的扩展库中,所以这里记得前面加上\'\\',thinkPHP此时就回去全区命名空间下
 56                 //  查找这个类问价
 57                 $pdf = new \PDFlib();
 58                 // PDF_begin_document() 这个方法在内存中创建一个pdf文档
 59                 if(false == $pdf->begin_document(\'\',\'\')) {
 60                     die(\'Error: \'.$pdf->get_errmsg());
 61                 }
 62 
 63                 $width = 792;
 64                 $height = 612;
 65                 // 向文档中添加新的页面
 66                 $pdf->begin_page_ext($width,$height,\'\');
 67             
 68                 // 开始定义并画出边框(pdf中的长度和位置的单位均是:像素)
 69                 $inset = 20; // 边框和页面边缘的距离
 70                 $border = 10; // 边框宽度
 71                 $inner = 2; // 边框和两条边线的距离
 72                 // PDF_rect 方法是画出一个矩形,注意坐标原点是 左下角
 73                 $pdf->rect($inset-$inner,$inset-$inner,$width-2*($inset-$inner),$height-2*($inset-$inner));
 74                 $pdf->stroke(); // PDF_stroke 描绘用当前颜色和路径宽度描绘出路径
 75                 
 76                 $pdf->setlinewidth($border);   // PDF_setlinewidth 设置线条宽度
 77                 $pdf->rect($inset+$border/2,
 78                    $inset+$border/2,
 79                    $width-2*($inset+$border/2),
 80                    $height-2*($inset+$border/2));
 81                 $pdf->stroke();
 82 
 83                 $pdf->setlinewidth(1.0);
 84                 $pdf->rect($inset+$border+$inner,
 85                         $inset+$border+$inner,
 86                         $width-2*($inset+$border+$inner),
 87                         $height-2*($inset+$border+$inner)
 88                         );
 89                 $pdf->stroke();
 90                 // 添加标题
 91                 $fontname = \'Times-Roman\';
 92                 // PDF_load_font 方法是:搜索和准备字体
 93                 $font = $pdf->load_font($fontname,\'winansi\',\'\');
 94                 $pdf->setcolor(\'fill\', \'rgb\', 1, 0, 0, 0); // PDF_setcolor  设置 填充颜色和描绘路径颜色
 95                 $pdf->setfont($font,20);
 96                 $pdf->show_xy($date,50,490);  // PDF_show_xy 在给的的位置输出文本内容
 97                 $pdf->setcolor(\'fill\', \'rgb\', 0, 0, 0, 0); // red
 98                 $pdf->setfont($font,48);
 99                 $start_x = ($width-$pdf->stringwidth(\'PHP Certification\',$font,\'12\'))/2;
100                 $pdf->show_xy(\'PHP Certification\',$start_x,490);
101                 
102                 // 添加内容
103                 $font = $pdf->load_font($fontname,\'iso8859-1\',\'\');
104                 $pdf->setfont($font,26);
105                 $start_x = 70;
106                 $pdf->show_xy(\'This is to certify that:\',$start_x,430);
107                 $pdf->show_xy(strtoupper($name),$start_x+90,391);
108 
109                 $font = $pdf->load_font($fontname,\'iso8859-1\',\'\');
110                 $pdf->setfont($font,20);
111                 $pdf->show_xy(\'has demonstrated that they are certifiable by passing a rigorous exam\', $start_x, 340);
112                 $pdf->show_xy(\'consisting of three multiple choice questions.\',$start_x, 310);
113                     
114                 $pdf->show_xy("$name obtained a score of $score".\'%.\', $start_x, 260);
115                     
116                 $pdf->show_xy(\'The test was set and overseen by the \', $start_x, 210);
117                 $pdf->show_xy(\'Fictional Institute of PHP Certification\', $start_x, 180);
118                 $pdf->show_xy("on $date.", $start_x, 150);
119                 $pdf->show_xy(\'Authorised by:\', $start_x, 100);
120 
121                 // 添加签名
122                 // PDF_load_image  打开图像文件
123                 $signature = $pdf->load_image(\'png\',WEB_ROOT."/Public/images/signature.png",\'\');
124                 $pdf->fit_image($signature,200, 75, \'\');  // PDF_fit_image 将图片放到指定位置
125                 $pdf->close_image($signature);  // 关闭文件
126                 
127                 // 开始画出星型图章 
128                 $pdf->setcolor(\'fill\', \'rgb\', 0, 0, .4, 0);  // 设置PDF_fill方法用的颜色
129                 $pdf->setcolor(\'stroke\', \'rgb\', 0, 0, 0, 0); // 设置PDF_stroke方法用的颜色
130                 // 画出左侧飘带
131                 $pdf->moveto(630, 150);  // PDF_moveto 将画图点移动到指定位置
132                 $pdf->lineto(610, 55);   // PDF_lineto 从当前点画出一条线到指定位置
133                 $pdf->lineto(632, 69);
134                 $pdf->lineto(646, 49);
135                 $pdf->lineto(666, 150);
136                 $pdf->closepath();   // PDF_closepath 关闭当前路径
137                 $pdf->fill();  // PDF_fill 用指定颜色填充到路径内 
138 
139                 // outline ribbon 1
140                 $pdf->moveto(630, 150);
141                 $pdf->lineto(610, 55);
142                 $pdf->lineto(632, 69);
143                 $pdf->lineto(646, 49);
144                 $pdf->lineto(666, 150);
145                 $pdf->closepath();
146                 $pdf->stroke();
147 
148                 // draw ribbon 2
149                 $pdf->moveto(660, 150);
150                 $pdf->lineto(680, 49);
151                 $pdf->lineto(695, 69);
152                 $pdf->lineto(716, 55);
153                 $pdf->lineto(696, 150);
154                 $pdf->closepath();
155                 $pdf->fill();
156 
157                 // -> outline ribbon 2
158                 $pdf->moveto(660, 150);
159                 $pdf->lineto(680, 49);
160                 $pdf->lineto(695, 69);
161                 $pdf->lineto(716, 55);
162                 $pdf->lineto(696, 150);
163                 $pdf->closepath();
164                 $pdf->stroke();
165 
166 
167                 $pdf->setcolor(\'fill\', \'rgb\', 1, 0, 0, 0); // red
168 
169                 //调用自定义方法,画出图章礼花
170                 $this->draw_star(665, 175, 32, 57, 10, $pdf, true);
171 
172                 //outline rosette
173                 $this->draw_star(665, 175, 32, 57, 10, $pdf, false);
174 
175                 // PDF_end_page 结束当前页
176                 
177                 // 这里如果需要继续制作第二页,第三页。。。。
178                 $pdf->end_page_ext("");
179 
180                     $pdf->set_info("Creator", "hello.php");
181                 $pdf->set_info("Author", "Rainer Schaaf");
182                 $pdf->set_info("Title", "Hello world (PHP)!");
183 
184                 $pdf->begin_page_ext(595, 842, "");
185 
186                 $font = $pdf->load_font("Helvetica-Bold", "winansi", "");
187 
188                 $pdf->setfont($font, 24.0);
189                 $pdf->set_text_pos(50, 700);
190                 $pdf->show("Hello world!");
191                 $pdf->continue_text("(says PHP)");
192                 $pdf->end_page_ext("");
193                 // 第二页结束,看明白了吗?
194 
195                 // PDF_end_document 结束文档 
196                 $pdf->end_document("");
197                 // PDF_get_buffer 得到PDF输出缓存
198                 $data = $pdf->get_buffer();
199 
200                 // 设置浏览器头信息
201                 header(\'Content-type: application/pdf\');
202                 header(\'Content-disposition: inline; filename=test.pdf\');
203                 header(\'Content-length: \' . strlen($data));
204 
205                 // 输出PDF
206                 echo $data;
207             }
208             catch (PDFlibException $e) {
209                 die("PDFlib exception occurred in hello sample:\n" .
210                         "[" . $e->get_errnum() . "] " . $e->get_apiname() . ": " .
211                         $e->get_errmsg() . "\n");
212             }
213             catch (Exception $e) {
214                     die($e);
215             }
216 
217         }
218     }
219     // 画礼花图章方法
220     // 具体算法自行理解,所用方法上面都有所说明,
221     function draw_star($centerx, $centery, $points, $radius, $point_size, $pdf, $filled)  {
222         $inner_radius = $radius-$point_size;
223 
224         for ($i = 0; $i<=$points*2; $i++)  {
225                 $angle= ($i*2*pi())/($points*2);
226 
227                 if($i%2) {
228                         $x = $radius*cos($angle) + $centerx;
229                         $y = $radius*sin($angle) + $centery;
230                 } else {
231                         $x = $inner_radius*cos($angle) + $centerx;
232                         $y = $inner_radius*sin($angle) + $centery;
233                 }
234 
235                 if($i==0) {
236                         $pdf->moveto($x, $y);
237                 } else if ($i==$points*2) {
238                         $pdf->closepath();
239                 } else {
240                         $pdf->lineto($x, $y);
241                 }
242         }
243         if($filled) {
244                 $pdf->fill_stroke();
245         } else {
246                 $pdf->stroke();
247         }
248     }
249 
250     public function pdf() {
251         try {
252                 $p = new \PDFlib();
253 
254                 /*  open new PDF file; insert a file name to create the PDF on disk */
255                 if ($p->begin_document("", "") == 0) {
256                         die("Error: " . $p->get_errmsg());
257                 }
258 
259                 $p->set_info("Creator", "hello.php");
260                 $p->set_info("Author", "Rainer Schaaf");
261                 $p->set_info("Title", "Hello world (PHP)!");
262 
263                 $p->begin_page_ext(595, 842, "");
264 
265                 $font = $p->load_font("Helvetica-Bold", "winansi", "");
266 
267                 $p->setfont($font, 24.0);
268                 $p->set_text_pos(50, 700);
269                 $p->show("Hello world!");
270                 $p->continue_text("(says PHP)");
271                 $p->end_page_ext("");
272 
273                 $p->end_document("");
274 
275                 $buf = $p->get_buffer();
276                 $len = strlen($buf);
277 
278                 header("Content-type: application/pdf");
279                 header("Content-Length: $len");
280                 header("Content-Disposition: inline; filename=hello.pdf");
281                 print $buf;
282                 $p->open_file(\'1.pdf\');
283         }
284         catch (PDFlibException $e) {
285                 die("PDFlib exception occurred in hello sample:\n" .
286                         "[" . $e->get_errnum() . "] " . $e->get_apiname() . ": " .
287                         $e->get_errmsg() . "\n");
288         }
289         catch (Exception $e) {
290                 die($e);
291         }
292         $p = 0;
293     }
294 }

    

    代码中用到的方法:

    PDF_begin_document() 这个方法在内存中创建一个pdf文档

    PDF_begin_page_ext()  向文档中添加新的页面

    PDF_rect          方法是画出一个矩形,注意坐标原点是 左下角

    PDF_stroke                  描绘用当前颜色和路径宽度描绘出路径

    PDF_setlinewidth         设置线条宽度

    PDF_load_font             搜索和准备字体.

    PDF_setcolor               设置 填充颜色和描绘路径颜色

    PDF_show_xy              在给的的位置输出文本内容

      PDF_load_image          打开图像文件

    PDF_fit_image            将图片放到指定位置

    PDF_close_image         关闭文件

      PDF_moveto              将画图点移动到指定位置

    PDF_lineto                 从当前点画出一条线到指定位置

    PDF_closepath           关闭当前路径

    PDF_fill                     用指定颜色填充到路径内

    PDF_end_document   结束文档

    PDF_get_buffer         得到PDF输出缓存

  好了,方法有很多,常用的也就是这么多,如果有兴趣,愿意的话可以去看看php手册:http://php.net/manual/zh/ref.pdf.php

 

  以上就是今天一天的学习成果,哎时间真快,都天黑了,完了,吃饭走。

  欢迎大家转载,收藏,吐槽,哈哈、、、、