PHP利用FPDI 制作PDF 档案 (php合并pdf, php签名pdf)

昨天研究如何在既有的PDF 档案上放入中文字,虽然找到支援中文的FPDF ,但是有些Unicode 字集我实在试不出如何显示(如:堃) 。

 

我的同事建议我用图形来解决看看,以下就是我的实验过程(我用的是Windows 平台) 。

 

我用的相关技术如下:

名称说明下载网址

FPDF PHP 上用来产生PDF 的第三方套件 [http://www.fpdf.org/](http://www.fpdf.org/)
FPDI 用来载入一个已存在的PDF 档案,以供FPDF 使用 [http://fpdi.setasign.de/](http://fpdi.setasign.de/)
香港参考宋体(DFSongSd.ttf) 包含许多Windows 内建中文字体所没有的中文字 [http://glyph.iso10646hk.net/index.jsp](http://glyph.iso10646hk.net/index.jsp)
GD 2 PHP 产生图形用的延伸套件 PHP Win32 内建
iconv 转换文字编码 PHP Win32 内建

 

首先,我利用FPDI 来载入一个已存在的PDF :

<?php
error_reporting (E_ALL);
require_once ('FPDI/FPDI.php');
// 建立 FPDI 物件
$pdf = new FPDI();
// 載入現在 PDF 檔案
$page_count = $pdf->setSourceFile("test.pdf");
// 匯入現在 PDF 檔案的第一頁
$tpl = $pdf->importPage(1);
// 在新的 PDF 上新增一頁
$pdf->addPage();
// 在新增的頁面上使用匯入的第一頁
$pdf->useTemplate($tpl);
// 輸出成本地端 PDF 檔案
$pdf->output("final.pdf", "F");
// 結束 FPDI 剖析器
$pdf->closeParsers();
?>

FPDI 是继承自FPDF 这个类别,所以它本身就算是一个加强型的FPDF 。 上面的程式会把现有PDF 的第一页输出成新的PDF 档案。

 

接着我把表单传送过来的文字,放到一个现有的图形档上。 这里有两种实作方式:如果HTML 页面编码是Big5 ,那么我会先把表单传送过来的文字用iconv 转成UTF-8 编码;如果HTML 页面编码已经是UTF-8 ,那么就不必再用iconv转换。 我采用的是第一种方式:

<?php
$text = isset($_POST['text']) ? trim($_POST['text']) : NULL;
$is_created = FALSE;
if ($text)
{
// 產生圖片
$img = imagecreatefrompng('test.png');
// 設定黑色畫筆
$black = imagecolorallocate($img, 0, 0, 0);
// 轉換文字編碼
$utf_text = iconv('big5', 'utf-8', $text);
// 繪製文字
imagettftext($img, 30, 0, 10, 40, $black, "DFSongSd.ttf", $utf_text);
// 儲存圖片
imagepng($img, 'final.png');
imagedestroy($img);
$is_created = TRUE;
}
?><!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=big5" />
<title>測試</title>
</head>
<body>
<form name="form1" id="form1" method="post" action="<?php echo $_SERVER['PHP_SELF']; ?>">
<input type="text" name="text" id="text" value="<?php%20echo%20$text;%20?>" />
<input type="submit" name="Submit" value="送出" />
<a href="./">重新製作</a>
</form>
<?php if ($is_created) { ?>
<img src="final.png" alt="<?php echo $text; ?>" />
<?php } ?>
</body>
</html>

如此一来在输入文字并按下送出钮后,就会在现有图片上加上指定的文字。 当然文字的位置要加以计算,我是先用最简单的方式来完成。

 

最后就是要将制作好的图片加到PDF 上了, FPDF 提供了image 函式来让我们可以在PDF 上放置图形。 实作方式如下:

// 產生圖片
$img = imagecreatefrompng('test.png');
$black = imagecolorallocate($img, 0, 0, 0);
$utf_text = iconv('big5', 'utf-8', $text);
imagettftext($img, 30, 0, 10, 40, $black, "DFSongSd.ttf", $utf_text);
imagepng($img, 'final.png');
imagedestroy($img);
// 載入現在 PDF 的第一頁
$pdf = new FPDI();
$page_count = $pdf->setSourceFile("test.pdf");
$tpl = $pdf->importPage(1);
$pdf->addPage();
$pdf->useTemplate($tpl);
// 放置圖形
$pdf->image("final.png", 75, 85, 50);
// 輸出成本地端 PDF 檔
$pdf->output("final.pdf", "F");
$pdf->closeParsers();

要注意的是,貼上去的圖形可以大一點,這樣縮小並貼到 PDF 時會有比較好的列印效果。而圖形的放置位置和大小,也要經過計算再貼上去。

 

原文:http://www.jaceju.net/blog/archives/55/

 

实例:

 

1. 导入完整pdf

<?php
require_once('fpdf/fpdf.php');
require_once('fpdi/fpdi.php');

// initiate FPDI
$pdf = new FPDI();

// get the page count
$pageCount = $pdf->setSourceFile('Performance_Fact_Sheet.pdf');

// iterate through all pages
for ($pageNo = 1; $pageNo <= $pageCount; $pageNo++) 
{
    // import a page
    $templateId = $pdf->importPage($pageNo);
    // get the size of the imported page
    $size = $pdf->getTemplateSize($templateId);

    // create a page (landscape or portrait depending on the imported page size)
    if ($size['w'] > $size['h']) {
        $pdf->AddPage('L', array($size['w'], $size['h']));
    } else {
        $pdf->AddPage('P', array($size['w'], $size['h']));
    }

    // use the imported page
    $pdf->useTemplate($templateId);

    $pdf->SetFont('Helvetica');
    $pdf->SetXY(5, 5);
    $pdf->Write(8, 'A complete document imported with FPDI');
}

// Output the new PDF
$pdf->Output();

2. 导入pdf的单页

<?php
require_once('fpdf/fpdf.php');
require_once('fpdi/fpdi.php');

// initiate FPDI
$pdf = new FPDI();
// add a page
$pdf->AddPage();
// set the source file
$pdf->setSourceFile("Fantastic-Speaker.pdf");
// import page 1
$tplIdx = $pdf->importPage(1);
// use the imported page and place it at point 10,10 with a width of 100 mm
$pdf->useTemplate($tplIdx, 10, 10, 100);

// now write some text above the imported page
$pdf->SetFont('Helvetica');
$pdf->SetTextColor(255, 0, 0);
$pdf->SetXY(30, 30);
$pdf->Write(0, 'This is just a simple text');

$pdf->Output();

3. 导入多pdf

<?php
require_once('fpdf/fpdf.php');
require_once('fpdi/fpdi.php');

// define some files to concatenate
$files = array(
    'Boombastic-Box.pdf',
    'Fantastic-Speaker.pdf',
    'Noisy-Tube.pdf'
);

// initiate FPDI
$pdf = new FPDI();

// iterate through the files
foreach ($files AS $file) {
    // get the page count
    $pageCount = $pdf->setSourceFile($file);
    // iterate through all pages
    for ($pageNo = 1; $pageNo <= $pageCount; $pageNo++) {
        // import a page
        $templateId = $pdf->importPage($pageNo);
        // get the size of the imported page
        $size = $pdf->getTemplateSize($templateId);

        // create a page (landscape or portrait depending on the imported page size)
        if ($size['w'] > $size['h']) {
            $pdf->AddPage('L', array($size['w'], $size['h']));
        } else {
            $pdf->AddPage('P', array($size['w'], $size['h']));
        }

        // use the imported page
        $pdf->useTemplate($templateId);

        $pdf->SetFont('Helvetica');
        $pdf->SetXY(5, 5);
        $pdf->Write(8, 'A simple concatenation demo with FPDI');
    }
}

// Output the new PDF
$pdf->Output();

4. 导入pdf文件,并且在最后一页签名

<?php
require_once('fpdf/fpdf.php');
require_once('fpdi/fpdi.php');

// initiate FPDI
$pdf = new FPDI();

// get the page count
$pageCount = $pdf->setSourceFile('Performance_Fact_Sheet.pdf');

// iterate through all pages
for ($pageNo = 1; $pageNo <= $pageCount; $pageNo++) 
{
    // import a page
    $templateId = $pdf->importPage($pageNo);
	
    // get the size of the imported page
    $size = $pdf->getTemplateSize($templateId);

    // create a page (landscape or portrait depending on the imported page size)
    if ($size['w'] > $size['h']) $pdf->AddPage('L', array($size['w'], $size['h']));
    else $pdf->AddPage('P', array($size['w'], $size['h']));
	
    // use the imported page
    $pdf->useTemplate($templateId);
	
	// sign when last page
	if($pageNo==$pageCount)
	{
	    // sign with your name
	    $pdf->SetFont('Arial','B','12');
	    $pdf->SetXY(68, 129); // you should keep testing untill you find out correct x,y values 
	    $pdf->Write(7, 'Gideon Liang');
		
	    // sign with current date
	    $pdf->SetXY(40, 144); // you should keep testing untill you find out correct x,y values 
	    $pdf->Write(7, '12/03/2014');
	} 
}

// Output the new PDF
$pdf->Output();

 

Leave a Reply