5

このスタックの質問を修正しました:ユーザーがファイルをダウンロードしようとしたときに PDF ファイルに透かしを適用すると、エラーが発生しました。

コードは次のとおりです。

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 を読み込むと、すべてのページが 1 ページにマージされます。この投稿に画像を添付しました。ここに画像の説明を入力

ありがとう。

4

3 に答える 3

8

このスクリプトにはいくつか問題があることがわかりました。それを機能させるには、メソッドを次のように変更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');
}

そうしないと、すべてが 1 ページに出力されるため、行$this->pdf->addPage();をループに移動しました。$this->_rotate(0);また、ドキュメントを保存する前に、ドキュメントを垂直に戻すことも追加しました。とてもシンプルです。変更された行についてコメントしました。

32 ページの pdf でテストしたところ、問題なく動作するように見えました。

于 2012-05-06T12:40:29.420 に答える
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());
}

とにかく、これがいつか誰かを助けることを願っています!

于 2014-09-07T01:09:55.163 に答える