2012-05-06 151 views
3

我修改了这个堆栈问题:Applying watermarks on pdf files when users try to download the files但我遇到了一个错误,虽然有评论说如何解决它,但它不够详尽。FPDI/FPDF:水印和打印多个页面

下面是代码:

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; 

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

    for($i = 1; $i <= $pagecount; $i++){ 
     $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->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)); 
    } 
    } 

} 
header('Content-type: application/pdf'); 
//header('Content-Disposition: attachment; filename="downloaded.pdf"'); 
WaterMark::applyAndSpit('C:\xampp\htdocs\tst\test0.pdf','C:\xampp\htdocs\tst\output0.pdf'); 

当我装载有2个以上所有页面的一个页面合并的PDF文件。我在这篇文章中附加了图片。 enter image description here

谢谢。

+0

@vascowhite任何想法如何解决这个问题? –

+0

不是,但我会先检查插入的内容。它看起来像整个页面旋转。对不起,但我对fpdf没有太多经验。我已经使用过它,但只用于非常基本的东西。如果今天晚些时候我有机会玩,我会看到我能找到的。祝你好运。 – vascowhite

+0

你见过这个吗? http://www.setasign.de/products/pdf-php-solutions/setapdf-stamper/ – vascowhite

回答

6

我发现该脚本有一些错误。得到它的工作改变doWatermark()方法如下: -

public function doWaterMark() 
{ 
    $currentFile = $this->file; 
    $newFile = $this->newFile; 

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

    for($i = 1; $i <= $pagecount; $i++){ 
     $this->pdf->addPage();//<- moved from outside loop 
     $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);//<-added 
    } 

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

我感动行$this->pdf->addPage();进入死循环,否则一切都输出到一页上。我还添加了$this->_rotate(0);,以便在保存文档之前将文档放回原位。真的很简单。我已经为你改变了评论。

我在32页pdf上测试过它,它似乎工作正常。

+0

任何想法如何设置透明度?我改变了与此类似的值,但没有得到任何结果。 http://www.fpdf.org/en/script/script9.php –

+0

这不是透明的,只是一个苍白的颜色,他们通过首先放入水印,然后把页面文本放在最上面来欺骗。 http://www.fpdf.org/en/script/watermark.pdf – vascowhite

+0

好的。如果pdf是扫描副本,这个窍门将不起作用。 –

2

这篇文章对我来说是一个很好的帮助。但我很快发现FPDF有几个人在这里遇到的一些陷阱。对我而言,我也注意到水印只显示在某些浏览器实例的第一页上,并通过Adobe Acrobat(Acrobat X Pro)打开。

相反,我切换到使用TCPDF,解决各种问题,包括:

  • 没有错误设置的角度时设置透明度
  • 自定义字体
  • 有能力
  • 更新功能:更新文本

要使用自定义字体,只需取消下面的自定义字体块的注释( http://www.tcpdf.org/fonts.php)。

另外,最后注意,标准FPDI软件包仅支持PDF版本1.4。因此,如果您导入任何高于此值的PDF,导入将无法正常工作并且炸毁。您需要购买商业版本(https://www.setasign.com/products/fpdi-pdf-parser/details/),或者将您的PDF保存在版本1.4,这就是我们所做的。

这里是我更新的代码:

require_once(APPPATH . 'third_party/tcpdf/tcpdf.php'); 
require_once(APPPATH . 'third_party/fpdi/fpdi.php'); 

class WatermarkerTCPDF extends FPDI { 
    public $pdf, $file, $newFile, 
      $wmText = "STACKOVERFLOW", 
      $fontsize = 24, 
      $fontfamily = 'ptsansnarrow400'; 

    /** $file and $newFile have to include the full path. */ 
    public function __construct($file = null, $newFile = null) { 
     $this->pdf = new FPDI(); 
     //custom fonts 
     //$this->fontfamily = $this->pdf->addTTFfont(APPPATH . 'third_party/tcpdf/ttf/ptsansnarrow400.ttf', 'TrueTypeUnicode', ''); 
     if (!empty($file)) { 
      $this->file = $file; 
     } 
     if (!empty($newFile)) { 
      $this->newFile = $newFile; 
     } 
    } 

    /** $file and $newFile have to include the full path. */ 
    public static function applyAndSpit($file, $newFile = null) { 
     $wm = new Watermarker($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++) { 
      $tplidx = $this->pdf->importPage($i); 
      $specs = $this->pdf->getTemplateSize($tplidx); 
      $this->pdf->SetPrintHeader(false); 
      $this->pdf->SetPrintFooter(false); 
      $this->pdf->addPage($specs['h'] > $specs['w'] ? 'P' : 'L'); 
      $this->pdf->useTemplate($tplidx, null, null, 0, 0, true); 

      // now write some text above the imported page 
      $this->pdf->SetFont($this->fontfamily, '', $this->fontsize); 
      $this->pdf->SetTextColor(204, 204, 204); 
      //$this->pdf->SetXY($specs['w']/2, $specs['h']/2); 
      $_x = ($specs['w']/2) - ($this->pdf->GetStringWidth($this->wmText, $this->fontfamily, '', $this->fontsize)/2.8); 
      $_y = $specs['h']/2; 
      $this->pdf->SetXY($_x, $_y); 
      //$this->pdf->SetXY(0, 0); 
      $this->pdf->setAlpha(0.3); 
      $this->_rotate(45, 100, 100); 
      $this->pdf->Write(0, $this->wmText); 
      //$this->pdf->writeHTMLCell($w=0, $h=0, $x='', $y='', $this->wmText, $border=0, $ln=1, $fill=0, $reseth=true, $align='', $autopadding=true); 
     } 

     if (empty($newFile)) { 
      header('Content-Type: application/pdf'); 
      $this->pdf->Output(); 
     } else { 
      $this->pdf->Output($newFile, 'F'); 
     } 
    } 

    public function isWaterMarked() { 
     //return (file_exists($this->newFile)); 
     $_file = $this->newFile; 
     $file = file_get_contents($_file); 
     force_download($file); 
    } 

    public function spitWaterMarked() { 
     $_file = $this->newFile; 
     $file = file_get_contents($_file); 
     force_download($file); 
     //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)); 
     } 
    } 

    public function wmText($text = null) 
    { 
     $total = 20; 
     if (!empty($text)) { 
      $this->wmText = ''; 
      for ($i = 0; $i < $total; $i++) { 
       $this->wmText .= ' ' . $text; 
      } 

     } 

     return $this; 
    } 
} 

要使用此,只是:

try { 
    //this is for CodeIgniter 
    $this->load->library('WatermarkerTCPDF'); 

    //if your using it as a standard class in vanilla PHP just do: 
    //require_once('PATH_TO_LIBRARY/WatermarkerPDF.php'); 

    //If you want to output the PDF to another file, you can supply 
    //a second parameter: new WatermarkerTCPDF($file_path, $new_file_path); 
    //just remember, the full path is required 
    $watermark = new WatermarkerTCPDF($file_path); 
    $watermark->wmText($this->session->userdata('email')); 
    $watermark->doWaterMark(); 
} catch (Exception $e) { 
    exit($e->getMessage()); 
} 

不管怎么说,希望这能帮助别人一天!

+0

帮助了我。你是一个拯救生命的人! –

+0

帮助了我。你是一个拯救生命的人! ²=) –