FPDI/FPDF: Watermark and Print Multiple Pages

前端 未结 3 1012
你的背包
你的背包 2021-02-03 15:42

I modified this stack question: Applying watermarks on pdf files when users try to download the files but I encountered an error, though there was a comment that says on how to

3条回答
  •  隐瞒了意图╮
    2021-02-03 16:32

    This post was a great help to me in getting things started. But I quickly found that FPDF had some pitfalls a few people here have been experiencing. For me, I also noticed that the watermark only displays on the first page in some browser instances as well as opening it up through adobe acrobat (Acrobat X Pro).

    Instead, I switched to using TCPDF, which solved a variety of problems including:

    • No errors when setting angles
    • Having ability to set transparency
    • Custom fonts
    • Updated Feature: Updating the text

    To use the custom fonts, just uncomment the custom font block below (http://www.tcpdf.org/fonts.php).

    Also, final note, the standard FPDI package only supports PDF version 1.4. So if your importing any PDF's that are above that, the import will not work and blow up. You will need to buy a commercial version (https://www.setasign.com/products/fpdi-pdf-parser/details/), or just save your PDFs at version 1.4, thats what we did.

    Here's my updated code:

    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;
        }
    }
    

    To use this, just:

    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());
    }
    

    Anyway, hope this will help someone someday!

提交回复
热议问题