我修改了这个堆栈问题:Applying watermarks on pdf files when users try to download the files但是我遇到了一个错误,虽然有一条评论说明如何修复它,但它还不够详细。
以下是代码:
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时,所有页面合并在一个页面中。我在这篇文章中附上了图片。
感谢。
答案 0 :(得分:7)
我发现该脚本存在一些问题。要使其正常工作,请将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上进行了测试,看起来效果很好。
答案 1 :(得分: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/),或者只保存1.4版本的PDF,这就是我们所做的。
这是我的更新代码:
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());
}
无论如何,希望有一天这会有所帮助!
答案 2 :(得分:0)
如果有人想使用FPDF并快速创建pdf而不必从文件中加载它,这就是我的方法。您将使用此类而不是FPDF类实例化PDF对象。该操作应在内存中创建pdf之后运行,但在输出之前:
<?php
include_once('fpdf.php');
class PDF_Rotate extends FPDF
{
var $angle=0;
public function ApplyWaterMarkToAllPages() {
for($i = 0; $i < count($this->pages); $i++) {
$this->page = $i;
$this->ApplyWaterMark();
}
}
private function ApplyWaterMark()
{
//Put the watermark
$this->SetFont('Arial','B',60);
$this->SetTextColor(255,192,203);
$this->RotatedText(15,280,'D O N O T F I L E - S A M P L E ',50);
$this->SetTextColor(0,0,0);
}
private function RotatedText($x, $y, $txt, $angle)
{
//Text rotated around its origin
$this->rotate($angle,$x,$y);
$this->Text($x,$y,$txt);
$this->Rotate(0);
}
private function Rotate($angle,$x=-1,$y=-1)
{
if($x==-1)
$x=$this->x;
if($y==-1)
$y=$this->y;
if($this->angle!=0)
$this->_out('Q');
$this->angle=$angle;
if($angle!=0)
{
$angle*=M_PI/180;
$c=cos($angle);
$s=sin($angle);
$cx=$x*$this->k;
$cy=($this->h-$y)*$this->k;
$this->_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));
}
}
function _endpage()
{
if($this->angle!=0)
{
$this->angle=0;
$this->_out('Q');
}
parent::_endpage();
}
}
?>
我有一个叫做Document的类,我把所有东西都放在了抽象中。这是它的输出函数。我创建了一个名为“ applyWaterMark”的类级别变量,以控制是否将水印应用于文档。
protected function OutputDocument() {
if($this->applyWaterMark) {
$this->pdf->ApplyWaterMarkToAllPages();
}
$this->pdf->Output();
}