2010-10-21 43 views
7

我学校的作业解决方案都带有用我们用户名登录的PDF文件。当用户尝试下载文件时,在PDF文件上应用水印

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

谢谢。

+0

他们的下载脚本可能会抓住你的用户名,创建基本图像,并使用'pdf_php'库层上的PDF顶部的形象。 – drudge 2010-10-21 00:49:50

+0

您是如何生成(或计划)PDF的?如果你还没有做任何事情,看看Webkit到PDF:http://code.google.com/p/wkhtmltopdf/ – Petah 2010-10-21 01:29:22

回答

5

尽管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); 
4

需要做到这一点昨天这里是如何没有任何外部非PHP库需要安装。只需要两个库就是两个PHP库,并且很容易获得。

  • FPDF - >http://www.fpdf.org/最新版本
  • FPDI - > ​​ (确保抛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 = "STACKOVERFLOW"; 

    /** $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); 
+0

我用这个,并获得所有页面显示在第一页。我可以通过在'doWaterMark()'的循环结尾添加'$ this-> pdf-> addPage();来解决这个问题。我做了一些其他小改动,所以我没有信心编辑你的答案,但如果其他人有这个问题,这可能会有所帮助。 – 2012-04-11 15:43:26

+0

我更正了此代码以回应[此问题](http://stackoverflow.com/q/10468478/212940) – vascowhite 2012-05-08 06:33:16

+0

感谢您的代码。到目前为止,我发现了几件小事,使它不再是即插即用的。 “运行这个”命令需要两个参数:WaterMark :: applyAndSpit($ fileWithFullPath,$ newfilenameWithFullPath); ,并且该类使用=&,在当前的php中已弃用,只是使用=。 – rpilkey 2015-11-05 14:05:57