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 

 

posted @ 2024-04-03 11:41  carol2014  阅读(445)  评论(0编辑  收藏  举报