32.3.4 从模板生成PDF证书

从模板生成PDF证书的过程非常相似。主要的差异在于当创建PDF文件时,某些占位符可能会被解释为一些格式化代码,这将根据所使用的Acrobat版本不同而不同。例如,如果我们查看所创建的证书模板(使用一个文本编辑器),可以看到占位符将变成:


<<N)-13(AME)-10(>)-6(>

<<Na)-9(m)0(e)-18(>>

<)-11(<)1(sc)-17(or)-6(e)-6(>)-11(>

<)-11(<)1(m)-12(m)0(/d)-6(d)-19(/)1(yy)-13(yy)-13(>>


如果阅读整个文件,将发现与RTF不同,这不是一个我们能够轻易理解的格式。

提示 根据所使用的Acrobat版本或其他PDF生成工具的不同,PDF模板文件也会有所不同。在以上示例所提供的代码可能无法适用于你所生成的模板。请检查模板并且相应地修改其中的代码。如果还存在问题,可以使用本章稍后给出的PDFlib示例。

对于这种情况,我们可以使用几种不同的办法来解决问题。可以检查每个占位符并删除这些格式化符号。事实上,删除这些格式化符号最终将不会太多改变文档外观,因为嵌入到前面模板中的代码表示了我们将要替代的占位字符之间需要留出多少空间。然而,如果采取这种方法,必须在每次修改或更新文件的时候,仔细检查并手动编辑PDF文件。如果仅有4个占位符的时候这也许并不是大问题,但是当需要处理有许多占位符的多个文档,并决定要修改所有文档的信头时,这将会是一件非常可怕的事情。

我们可以通过使用其他技巧来避免此问题。可以用Adobe Acrobat来创建一个PDF表单——与带有空白命名域的HTML表单相似。然后可以用PHP脚本创建所谓的FDF(Forms Data Format)文件,该文件主要是一些将要合并到模板中的数据。可以用PHP的FDF函数库创建FDF:fdf_create()函数创建一个文件:fdf_set_value()函数设置表单域的值;fdf_set_file()函数设置相关的模板表单文件。可以用适当的MIME类型将该文件返回到浏览器中(在这个例子中,MIME类型是vnd.fdf),并且用浏览器的Acrobat Reader插件程序来替换数据并填充到表单中。

这是一个非常巧妙的方法,但是,它也有两点局限性。首先,它需要一份Acrobat专业版的副本(完整版本,不是免费的阅读器,也不是标准版)。其次,在行内的文本而非表单域中进行文本替换是相当困难的。这可能是一个问题,但也可能不是问题,这是由具体操作来决定的。我们已在需要成行地替换许多文本的地方大量使用PDF生成功能来生成字符。FDF不能很好地完成这个功能。例如,如果自动填充一个在线税收表单,这不会成为一个问题。

在Adobe站点,可以看到更多关于FDF格式的介绍:http://www.adobe.com/devnet/acrobat/fdftoolkit.html。

如果打算使用这种方法的话,还应该查看PHP手册中的FDF文档:http://www.php.net/manual/en/ref.fdf.php。

现在,我们回到解决前面问题的PDF方案。

如果我们可以确认附加的格式代码只是由单个的连字符、阿拉伯数字及圆括号组成,并且能够通过正则表达式进行匹配,那么我们仍然可在PDF文件中找出并替换这些占位符。我们已经写了一个pdf_replace()函数来自动地生成某个占位符的匹配正则表达式,并能用适当的文本替代该占位符。

请注意,在Acrobat的某些版本中,占位符以纯文本格式出现。正如前面所介绍的,可以用str_replace()函数来替换它们。

除了这点外,通过PDF模板生成证书的代码与RTF版本的也非常相似,该脚本程序如程序清单32-4所示。

程序清单32-4 pdf.php——通过模板产生个性化PDF证书的脚本程序


<?php

set_time_limit(180);//this script can be slow

//create short variable names

$name=$_POST['name'];

$score=$_POST['score'];

function pdf_replace($pattern,$replacement,$string){

$len=strlen($pattern);

$regexp='';

for($i=0;$i<$len;$i++){

$regexp.=$pattern[$i];

if($i<$len-1){

$regexp.="()-{0,1}[0-9]*(){0,1}";

}

}

return ereg_replace($regexp,$replacement,$string);

}

if(!$name||!$score){

echo"<h1>Error:</h1>

<p>This page was called incorrectly</p>";

}else{

//generate the headers to help a browser choose the correct application

header('Content-Disposition:filename=cert.pdf');

header('Content-type:application/pdf');

$date=date('F d,Y');

//open our template file

$filename='PHPCertification.pdf';

$fp=fopen($filename,'r');

//read our template into a variable

$output=fread($fp,filesize($filename));

fclose($fp);

//replace the place holders in the template with our data

$output=pdf_replace('<<NAME>>',strtoupper($name),$output);

$output=pdf_replace('<<Name>>',$name,$output);

$output=pdf_replace('<<score>>',$score,$output);

$output=pdf_replace('<<mm/dd/yyyy>>',$date,$output);

//send the generated document to the browser

echo$output;

}

?>


该脚本产生PDF文档的一个自定义版本。如图32-6所示,该文档在多数系统中可以稳定地打印出来,且接收者无法修改其内容。我们会发现图32-6中的PDF文档看起来很像图32-5中的RTF文档。

32.3.4 从模板生成PDF证书 - 图1

图 32-6 pdf.php用PDF模板生成证书

该方法的一个问题是由于正则表达式的匹配使得该代码的运行速度非常慢。正则表达式比在RTF版本中用到的str_replace()函数要慢得多。

如果要在相同的服务器上匹配大量的占位符,或者试图生成许多这样的文档,可能需要寻求其他方法。而对于简单的模板,这个问题稍小一些。该文件中的大部分数据都是表示图像。