添加链接
link之家
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接
相关文章推荐
爱看书的竹笋  ·  nosuchmethoderror ...·  1 年前    · 
欢乐的打火机  ·  Matlab绘图 - 知乎·  1 年前    · 

最近要开发给pdf文件增加水印的程序,因此研究了几个php生成pdf的类库,记录下。

首先要能够读入pdf文件,然后给pdf文件增加水印,然后能够导出。检索资料发现FPDI可以读入pdf文件。

FPDI安装

先安装下几个库,以备后面使用:

"require": { "setasign/fpdf": "^1.8", "setasign/fpdi": "^2.6", "setasign/tfpdf": "^1.33", "tecnickcom/tcpdf": "6.6.*", "mpdf/mpdf": "^8.2"

生成demo使用的pdf文件

require_once  './libs/vendor/autoload.php';
$mpdf = new \Mpdf\Mpdf();
$mpdf->autoScriptToLang = true;
$mpdf->autoLangToFont = true;
$mpdf->WriteHTML('中文EN中文');
$mpdf->Output('./files/out.pdf', 'F');

生成pdf文件如下:

使用FPDI给pdf文件增加水印

require_once './libs/vendor/autoload.php'; use setasign\Fpdi\Fpdi; $pdf = new Fpdi(); // 打开现有的PDF文件 $pageCount = $pdf->setSourceFile('./files/out.pdf'); for ($pageNo = 1; $pageNo <= $pageCount; $pageNo++) { $templateId = $pdf->importPage($pageNo); $pdf->AddPage(); $pdf->useTemplate($templateId, ['adjustPageSize' => true]); //文字水印 $pdf->SetFont('Arial', '', 10); $pdf->SetTextColor(200, 200, 200); $pdf->SetXY(20, 50); $pdf->Write(0, 'Watermark'); $pdf->SetXY(60, 50); $pdf->Write(0, iconv('utf-8', 'gbk', '水印')); //中文乱码 $pdf->SetXY(100, 50); $pdf->Write(0, '水印'); //中文乱码 // 图片水印 $pdf->image("./files/1.jpg", 75, 85, 50); $pdf->Output(); // $pdf->Output('F', './files/watermarked_pdf.pdf');// 下载修改后的PDF

显示如下:中文水印乱码

按照别人的经验使用中文包,下载中文包  http://www.fpdf.org/download/chinese.zip 将chinese.php重命名为FPDF_Chinese.php,并修改内容,放置到vendor/setasign/fpdf目录下

class FPDF_Chinese extends FPDF
	private $Big5_widths = array(...);
	private $GB_widths = array(...);
	function AddBig5Font($family = 'Big5', $name = 'MSungStd-Light-Acro')
		// Add Big5 font with proportional Latin
		$cw = $this->Big5_widths;
		$CMap = 'ETenms-B5-H';
	function AddGBFont($family = 'GB', $name = 'STSongStd-Light-Acro')
		// Add GB font with proportional Latin
		$cw = $this->GB_widths;
		$CMap = 'GBKp-EUC-H';

查看自动加载文件及composer目录代码,临时修改vendor/composer目录下autoload_static.php文件,在$classMap中增加1行,使FPDF_Chinese可以被自动加载:

 public static $classMap = array(
        'FPDF' => __DIR__ . '/..' . '/setasign/fpdf/fpdf.php',
        'FPDF_Chinese' => __DIR__ . '/..' . '/setasign/fpdf/FPDF_Chinese.php',

修改vendor/setasign/fpdi/src/FpdfTpl.php文件使FpdfTpl继承自FPDF_Chinese

// class FpdfTpl extends \FPDF
class FpdfTpl extends \FPDF_Chinese
    use FpdfTplTrait;

在上面的代码中增加字体:

require_once './libs/vendor/autoload.php'; use setasign\Fpdi\Fpdi; $pdf = new Fpdi(); $pdf->AddGBFont(); $pdf->SetFont('GB');

然后报错了

几经折腾,发现无法解决这个问题,去FPDF的论坛里面发现了这个:

作者推荐使用tFPDF 适配中文字体

使用tFPDF给pdf文件添加水印 

require_once './libs/vendor/autoload.php'; $pdf = new \setasign\Fpdi\Tfpdf\Fpdi(); // $pdf->AddFont('DejaVuSansCondensed', '', 'DejaVuSansCondensed.ttf', true);//中文不显示 // $pdf->SetFont('DejaVuSansCondensed', '', 14); // $pdf->AddFont('Arial', '', 'Arial.ttf', true);//中文不显示 // $pdf->SetFont('Arial', '', 14); $pdf->AddFont('msyh', '', 'msyh.ttf', true); //简体中文可正常显示 $pdf->SetFont('msyh', '', 14); $pageCount = $pdf->setSourceFile('./files/out.pdf'); for ($pageNo = 1; $pageNo <= $pageCount; $pageNo++) { $templateId = $pdf->importPage($pageNo); $pdf->AddPage(); $pdf->useTemplate($templateId, ['adjustPageSize' => true]); //文字水印 $pdf->SetTextColor(200, 200, 200); $pdf->SetXY(20, 30); $pdf->Write(0, 'Watermark'); $pdf->SetXY(80, 30); $pdf->Write(0, '水印'); // 图片水印 $pdf->image("./files/1.jpg", 20, 40, 50); $pdf->Output(); // $pdf->Output('F', './files/watermarked_pdf.pdf'); //下载修改后的PDF

过程中经历了 自带的DejaVuSans字体显示为方块,自己找到两个字体Arial.ttf、msyh.ttf放置到vendor/setasign/tfpdf/font/unifont目录,最终msyh可以正常显示

使用TCPDF给pdf文件添加水印  

require_once './libs/vendor/autoload.php'; $pdf = new \setasign\Fpdi\Tcpdf\Fpdi(); $pdf->SetFont('msyh', '', 14); $pageCount = $pdf->setSourceFile('./files/out.pdf'); for ($pageNo = 1; $pageNo <= $pageCount; $pageNo++) { $templateId = $pdf->importPage($pageNo); $pdf->AddPage(); $pdf->useTemplate($templateId, ['adjustPageSize' => true]); //文字水印 $pdf->SetTextColor(200, 200, 200); $pdf->SetXY(20, 30); $pdf->Write(0, 'Watermark'); $pdf->SetXY(80, 30); $pdf->Write(0, '水印'); // 图片水印 $pdf->image("./files/1.jpg", 20, 40, 50); $pdf->Output();

 TCPDF的中文字体解决方案见 php将html生成为pdf文件之tcpdf、mpdf、dompdf简单使用 - carol2014 - 博客园 (cnblogs.com)

使用mpdf给pdf文件添加水印

require_once './libs/vendor/autoload.php'; $defaultConfig = (new Mpdf\Config\ConfigVariables())->getDefaults(); $fontDirs = $defaultConfig['fontDir']; $defaultFontConfig = (new Mpdf\Config\FontVariables())->getDefaults(); $fontData = $defaultFontConfig['fontdata']; $mpdf = new \Mpdf\Mpdf([ 'mode' => '+aCJK', 'fontDir' => array_merge($fontDirs, [__DIR__ . '/fonts']), 'fontdata' => $fontData + 'msyh' => [ 'R' => 'msyh.ttf', 'default_font' => 'msyh' $mpdf->autoScriptToLang = true; $mpdf->autoLangToFont = true; $text = 'watermark水印'; //文字水印 $watermarkText = new \Mpdf\WatermarkText($text, 5, 30, '#996633', 0.4); $mpdf->SetWatermarkText($watermarkText, 0.3); $mpdf->showWatermarkText = true; $mpdf->watermarkAngle = '0'; //图片水印 $mpdf->SetWatermarkImage('./files/1.jpg', 0.3); $mpdf->showWatermarkImage = true; $pageCount = $mpdf->SetSourceFile('./files/out.pdf'); //读取原始文件页数 for ($i = 1; $i <= $pageCount; $i++) { $import_page = $mpdf->ImportPage($i); $mpdf->UseTemplate($import_page); if ($i < $pageCount) $mpdf->AddPage(); $mpdf->Output(); // $mpdf->Output('./files/new.pdf', 'F');

显示如下:水印的颜色和角度可设置,文字大小设置未生效,文字及图片位置还没找到方法修改

可以看到mpdf读pdf的程式和FPDI类似,看下mpdf的包,果然依赖FPDI