当用户尝试下载文件时在 pdf 文件上应用水印

Posted

技术标签:

【中文标题】当用户尝试下载文件时在 pdf 文件上应用水印【英文标题】:Applying watermarks on pdf files when users try to download the files 【发布时间】:2011-04-28 08:38:31 【问题描述】:

我学校作业的解决方案都在 PDF 上带有我们的用户名的水印。

我想知道你们是否知道如何使用 php 做类似的事情?他们是否在下载过程之前运行脚本?

谢谢。

【问题讨论】:

他们的下载脚本可能会获取您的用户名,创建一个基本图像,然后使用pdf_php 库将该图像分层到 PDF 之上。 您是如何生成(或计划生成)PDF 的?如果您还没有做任何事情,请查看 Webkit to PDF:code.google.com/p/wkhtmltopdf 【参考方案1】:

虽然有几个非常好的 PHP 的 PDF 库,但如果我正在编写这样的程序,我会直接运行 pdftk,但您仍然需要生成水印。

$tempfile=tempnam();
system("pdftk input_file.pdf background watermark.pdf output $tempfile dont_ask", $errcode);
if (!$errcode && $ih=fopen($tempfile, 'r')) 
    header('Content-Type: application/pdf');
    fpassthru($ih);
    fclose($ih);
 else 
    print "Whoops";

unlink($tempfile);

【讨论】:

【参考方案2】:

昨天需要这样做,这就是不需要安装任何外部非 PHP 库的方法。唯一需要的 2 个库都是 PHP 库,而且很容易获得。

FPDF -> http://www.fpdf.org/ 最新 版本 FPDI-> http://www.setasign.de/products/pdf-php-solutions/fpdi/downloads/ (确保抛出 fpdf_tpl.php 与 fpdi.php 位于同一文件夹中的文件)

现在你可以使用下面的类来实现水印

/** MAKE SURE TO HAVE THE INCLUDES RUNNING PROPERLY */
require_once('FPDF/fpdf.php');
require_once('FPDI/fpdi.php');

class WaterMark

    public $pdf, $file, $newFile,
        $wmText = "***";

    /** $file and $newFile have to include the full path. */
    public function __construct($file, $newFile)
    
        $this->pdf =& new FPDI();
        $this->file = $file;
        $this->newFile = $newFile;
    

    /** $file and $newFile have to include the full path. */
    public static function applyAndSpit($file, $newFile)
    
        $wm = new WaterMark($file, $newFile);

        if($wm->isWaterMarked())
            return $wm->spitWaterMarked();
        else
            $wm->doWaterMark();
            return $wm->spitWaterMarked();
        
    

    /** @todo Make the text nicer and add to all pages */
    public function doWaterMark()
    
        $currentFile = $this->file;
        $newFile = $this->newFile;

        $pagecount = $this->pdf->setSourceFile($currentFile);

        for($i = 1; $i <= $pagecount; $i++)
                            $this->pdf->addPage();
            $tplidx = $this->pdf->importPage($i);
            $this->pdf->useTemplate($tplidx, 10, 10, 100);
            // now write some text above the imported page
            $this->pdf->SetFont('Arial', 'I', 40);
            $this->pdf->SetTextColor(255,0,0);
            $this->pdf->SetXY(25, 135);
            $this->_rotate(55);
            $this->pdf->Write(0, $this->wmText);
                            $this->_rotate(0);
        

        $this->pdf->Output($newFile, 'F');
    

    public function isWaterMarked()
    
        return (file_exists($this->newFile));
    

    public function spitWaterMarked()
    
        return readfile($this->newFile);
    

    protected function _rotate($angle,$x=-1,$y=-1) 

        if($x==-1)
            $x=$this->pdf->x;
        if($y==-1)
            $y=$this->pdf->y;
        if($this->pdf->angle!=0)
            $this->pdf->_out('Q');
        $this->pdf->angle=$angle;

        if($angle!=0)
            $angle*=M_PI/180;
            $c=cos($angle);
            $s=sin($angle);
            $cx=$x*$this->pdf->k;
            $cy=($this->pdf->h-$y)*$this->pdf->k;

            $this->pdf->_out(sprintf(
                'q %.5f %.5f %.5f %.5f %.2f %.2f cm 1 0 0 1 %.2f %.2f cm',
                $c,$s,-$s,$c,$cx,$cy,-$cx,-$cy));
        
     


您现在可以这样运行:

WaterMark::applyAndSpit($fileWithFullPath);

【讨论】:

我使用了这个并且所有页面都显示在第一页上。我可以通过将$this-&gt;pdf-&gt;addPage(); 添加到doWaterMark() 的循环末尾来解决此问题。我做了一些其他的小改动,所以我没有信心编辑你的答案,但如果其他人有这个问题,这可能会有所帮助。 我更正了此代码以响应this question 感谢您的代码。到目前为止,我发现有几件小事阻止了即插即用。 “运行这个”命令需要两个参数: WaterMark::applyAndSpit($fileWithFullPath,$newfilenameWithFullPath); ,并且该类使用 =&,在当前 php 中已弃用,只需使用 = .【参考方案3】:

有一个优秀的开源 php 库 http://www.tcpdf.org/ ,我将它用于所有 pdf 生成任务。

【讨论】:

【参考方案4】:

以下是我尝试使用 fpdi 进行水印的步骤:

<?php
use setasign\Fpdi\Fpdi;
use setasign\Fpdi\PdfReader;
    function PlaceWatermark($file, $text, $xxx, $yyy, $op, $outdir) 
require_once('fpdi/vendor/autoload.php');
require_once 'fpdi/vendor/setasign/fpdf/fpdf.php';
function copyTransparent($src, $output)
    
        $dimensions = getimagesize($src);
        $x = $dimensions[0];
        $y = $dimensions[1];
        $im = imagecreatetruecolor($x,$y); 
        $src_ = imagecreatefrompng($src); 
        // Prepare alpha channel for transparent background
        $alpha_channel = imagecolorallocatealpha($im, 255, 255, 255, 127); 
        imagecolortransparent($im, $alpha_channel); 
        // Fill image
        imagefill($im, 0, 0, $alpha_channel); 
        // Copy from other
        imagecopy($im,$src_, 0, 0, 0, 0, $x, $y); 
        // Save transparency
        imagesavealpha($im,true); 
        // Save PNG
        imagepng($im,$output,9); 
        imagedestroy($im); 
    
$png = 'https://www.office-deals.nl/images/logo_60x37.png';

    copyTransparent($png,"png.png");
$imageURL = 'png.png'; 

     $imgWidth = 20;
$pdf = new FPDI();
    if (file_exists("./".$file))
        $pagecount = $pdf->setSourceFile($file);
     else 
        return FALSE;
    
for($i=1; $i <= $pagecount; $i++)  
     $tpl = $pdf->importPage($i);               
     $pdf->addPage(); 
     $pdf->useTemplate($tpl, 5, 5);
$pdf->Image($imageURL, $xxx, $yyy,'png');



    if ($outdir === TRUE)
        return $pdf->Output($file,'I');
     else 
        return $pdf->Output();
    

$images='https://www.office-deals.nl/images/logo_60x37.png';
PlaceWatermark("laravel.pdf", $images, 180, 275, 100,TRUE);
?>

【讨论】:

以上是关于当用户尝试下载文件时在 pdf 文件上应用水印的主要内容,如果未能解决你的问题,请参考以下文章

怎么给PDF文件添加上水印

PDF文件添加二维码水印

如何给PDF文件添加图片水印

怎么给PDF文件添加水印?

pdf文件下载水印添加的中文与空格问题解决

给PDF文件添加水印的方法(图片水印)