2012-05-06 183 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

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