php给pdf文件加上水印
最近要开发给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文件增加水印
<?php
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;
}
在上面的代码中增加字体:
<?php
require_once './libs/vendor/autoload.php';
use setasign\Fpdi\Fpdi;
$pdf = new Fpdi();
$pdf->AddGBFont();
$pdf->SetFont('GB');
....
然后报错了
几经折腾,发现无法解决这个问题,去FPDF的论坛里面发现了这个:
作者推荐使用tFPDF 适配中文字体
使用tFPDF给pdf文件添加水印
<?php
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文件添加水印
<?php
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文件添加水印
<?php
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