将PDF文件与PHP合并

将PDF文件与PHP合并,php,pdf,Php,Pdf,我的概念是——一个网站中有10个pdf文件。用户可以选择一些pdf文件,然后选择“合并”以创建包含所选页面的单个pdf文件。如何使用php实现这一点?我以前就做过。我有一个用fpdf生成的pdf,我需要在其中添加不同数量的pdf 所以我已经设置了fpdf对象和页面(http://www.fpdf.org/) 我用fpdi导入文件(http://www.setasign.de/products/pdf-php-solutions/fpdi/) FDPI是通过扩展PDF类添加的: class PDF

我的概念是——一个网站中有10个pdf文件。用户可以选择一些pdf文件,然后选择“合并”以创建包含所选页面的单个pdf文件。如何使用php实现这一点?

我以前就做过。我有一个用fpdf生成的pdf,我需要在其中添加不同数量的pdf

所以我已经设置了fpdf对象和页面(http://www.fpdf.org/) 我用fpdi导入文件(http://www.setasign.de/products/pdf-php-solutions/fpdi/) FDPI是通过扩展PDF类添加的:

class PDF extends FPDI
{

} 



    $pdffile = "Filename.pdf";
    $pagecount = $pdf->setSourceFile($pdffile);  
    for($i=0; $i<$pagecount; $i++){
        $pdf->AddPage();  
        $tplidx = $pdf->importPage($i+1, '/MediaBox');
        $pdf->useTemplate($tplidx, 10, 10, 200); 
    }
类PDF扩展了FPDI { } $pdffile=“Filename.pdf”; $pagecount=$pdf->setSourceFile($pdffile); 对于($i=0;$iAddPage(); $tplidx=$pdf->importPage($i+1,'/MediaBox'); $pdf->useTemplate($tplidx,10,10200); }
这基本上是将每个pdf转换成一个图像,然后放入另一个pdf中。对于我所需要的内容,它工作得非常好。

下面是php pdf merge命令

$fileArray= array("name1.pdf","name2.pdf","name3.pdf","name4.pdf");

$datadir = "save_path/";
$outputName = $datadir."merged.pdf";

$cmd = "gs -q -dNOPAUSE -dBATCH -sDEVICE=pdfwrite -sOutputFile=$outputName ";
//Add each pdf file to the end of the command
foreach($fileArray as $file) {
    $cmd .= $file." ";
}
$result = shell_exec($cmd);
我忘了从哪里找到的链接,但它工作正常


注意:您应该安装gs(在linux上,可能是Mac上)或Ghostscript(在windows上)才能工作。

我建议PDFMerger来自,非常简单,如:

include 'PDFMerger.php';

$pdf = new PDFMerger;

$pdf->addPDF('samplepdfs/one.pdf', '1, 3, 4')
    ->addPDF('samplepdfs/two.pdf', '1-2')
    ->addPDF('samplepdfs/three.pdf', 'all')
    ->merge('file', 'samplepdfs/TEST2.pdf'); // REPLACE 'file' WITH 'browser', 'download', 'string', or 'file' for output options

myokyawhtun的解决方案最适合我(使用PHP5.4)

尽管如此,您仍然会收到一个错误-我使用以下方法解决了此问题:

fpdf_tpl.php的第269行-将函数参数更改为:

function Image($file, $x=null, $y=null, $w=0, $h=0, $type='', $link='',$align='', $resize=false, $dpi=300, $palign='', $ismask=false, $imgmask=false, $border=0) { 
我在fpdf.php的第898行也做了同样的更改

$cmd = "gs -q -dNOPAUSE -dBATCH -sDEVICE=pdfwrite -sOutputFile=".$new." ".implode(" ", $files);
shell_exec($cmd);

Chauhan答案的简化版本

我在FPDI上创建了一个抽象层(可以容纳其他引擎)。 根据库的不同,我将其发布为Symfony2包,并将其发布为库本身

用法:

public function handlePdfChanges(Document $document, array $formRawData)
{
    $oldPath = $document->getUploadRootDir($this->kernel) . $document->getOldPath();
    $newTmpPath = $document->getFile()->getRealPath();

    switch ($formRawData['insertOptions']['insertPosition']) {
        case PdfInsertType::POSITION_BEGINNING:
            // prepend 
            $newPdf = $this->pdfManager->insert($oldPath, $newTmpPath);
            break;
        case PdfInsertType::POSITION_END: 
            // Append
            $newPdf = $this->pdfManager->append($oldPath, $newTmpPath);
            break;
        case PdfInsertType::POSITION_PAGE: 
            // insert at page n: PdfA={p1; p2; p3}, PdfB={pA; pB; pC} 
            // insert(PdfA, PdfB, 2) will render {p1; pA; pB; pC; p2; p3} 
            $newPdf = $this->pdfManager->insert(
                    $oldPath, $newTmpPath, $formRawData['insertOptions']['pageNumber']
                );
            break;
        case PdfInsertType::POSITION_REPLACE: 
            // does nothing. overrides old file.
            return;
            break;
    }
    $pageCount = $newPdf->getPageCount();
    $newPdf->renderFile($mergedPdfPath = "$newTmpPath.merged");
    $document->setFile(new File($mergedPdfPath, true));
    return $pageCount;
}

这在Windows上对我有效


  • 免费下载PDFtk
  • 将文件夹(PDFtk)放到c的根目录中:
  • 将以下内容添加到php代码中,$file1是第一个PDF文件的位置和名称,$file2是第二个PDF文件的位置和名称,$newfile是目标文件的位置和名称

    $file1 = ' c:\\\www\\\folder1\\\folder2\\\file1.pdf';  
    $file2 = ' c:\\\www\\\folder1\\\folder2\\\file2.pdf';  
    $file3 = ' c:\\\www\\\folder1\\\folder2\\\file3.pdf';   
    
    $command =  'cmd /c C:\\\pdftk\\\bin\\\pdftk.exe '.$file1.$file2.$newfile;
    $result = exec($command);
    

  • 我的软件也有类似的问题。我们想将几个PDF文件合并成一个PDF文件并提交给外部服务。我们一直在使用FPDI解决方案,如克里斯塔的解决方案所示

    但是,我们使用的输入PDF的版本可能高于1.7。我们决定评估FPDI商业附加组件。但是,结果发现,我们的office复印机扫描的一些文档的索引格式错误,导致商业FPDI附加组件崩溃。因此,我们决定使用Ghostscript解决方案就像乔汉的回答一样

    但是我们在输出的PDF属性中得到了一些奇怪的元数据

    最后,我们决定加入两个解决方案,通过Ghostscript合并并降级PDF,但元数据是由FPDI设置的。我们还不知道它如何与一些高级格式的PDF一起工作,但对于扫描,我们使用它工作得很好。下面是我们的课程摘录:

    class MergedPDF extends \FPDI
    {
        private $documentsPaths = array();
    
        public function Render()
        {
            $outputFileName = tempnam(sys_get_temp_dir(), 'merged');
    
            // merge files and save resulting file as PDF version 1.4 for FPDI compatibility
            $cmd = "/usr/bin/gs -q -dNOPAUSE -dBATCH -dCompatibilityLevel=1.4 -sDEVICE=pdfwrite -sOutputFile=$outputFileName";
            foreach ($this->getDocumentsPaths() as $pdfpath) {
                $cmd .= " $pdfpath ";
            }
            $result = shell_exec($cmd);
            $this->SetCreator('Your Software Name');
            $this->setPrintHeader(false);
            $numPages = $this->setSourceFile($outputFileName);
            for ($i = 1; $i <= $numPages; $i++) {
                $tplIdx = $this->importPage($i);
                $this->AddPage();
                $this->useTemplate($tplIdx);
            }
    
            unlink($outputFileName);
    
            $content = $this->Output(null, 'S');
    
            return $content;
        }
    
        public function getDocumentsPaths()
        {
            return $this->documentsPaths;
        }
    
        public function setDocumentsPaths($documentsPaths)
        {
            $this->documentsPaths = $documentsPaths;
        }
    
        public function addDocumentPath($documentPath)
        {
            $this->documentsPaths[] = $documentPath;
        }
    }
    

    我尝试过类似的问题,效果很好,试试看。它可以处理PDF之间的不同方向

        // array to hold list of PDF files to be merged
        $files = array("a.pdf", "b.pdf", "c.pdf");
        $pageCount = 0;
        // initiate FPDI
        $pdf = new FPDI();
    
        // iterate through the files
        foreach ($files AS $file) {
            // get the page count
            $pageCount = $pdf->setSourceFile($file);
            // iterate through all pages
            for ($pageNo = 1; $pageNo <= $pageCount; $pageNo++) {
                // import a page
                $templateId = $pdf->importPage($pageNo);
                // get the size of the imported page
                $size = $pdf->getTemplateSize($templateId);
    
                // create a page (landscape or portrait depending on the imported page size)
                if ($size['w'] > $size['h']) {
                    $pdf->AddPage('L', array($size['w'], $size['h']));
                } else {
                    $pdf->AddPage('P', array($size['w'], $size['h']));
                }
    
                // use the imported page
                $pdf->useTemplate($templateId);
    
                $pdf->SetFont('Helvetica');
                $pdf->SetXY(5, 5);
                $pdf->Write(8, 'Generated by FPDI');
            }
        }
    
    //用于保存要合并的PDF文件列表的数组
    $files=数组(“a.pdf”、“b.pdf”、“c.pdf”);
    $pageCount=0;
    //启动FPDI
    $pdf=新的FPDI();
    //遍历这些文件
    foreach($files作为$file){
    //获取页面计数
    $pageCount=$pdf->setSourceFile($file);
    //遍历所有页面
    对于($pageNo=1;$pageNo importPage($pageNo);
    //获取导入页面的大小
    $size=$pdf->getTemplateSize($templateId);
    //创建页面(横向或纵向,取决于导入的页面大小)
    如果($size['w']>$size['h']){
    $pdf->AddPage('L',数组($size['w'],$size['h']);
    }否则{
    $pdf->AddPage('P',数组($size['w'],$size['h']);
    }
    //使用导入的页面
    $pdf->useTemplate($templateId);
    $pdf->SetFont('Helvetica');
    $pdf->SetXY(5,5);
    $pdf->Write(8,‘由FPDI生成’);
    }
    }
    
    无论是公认的答案,还是FDPI主页,似乎都给出了拙劣或不完整的示例。以下是我的示例,很容易实现。正如预期的那样,它需要fpdf和fpdi库:

    • FPDF:
    • FPDI:
    require('fpdf.php');
    require('fpdi.php');
    $files=['doc1.pdf','doc2.pdf','doc3.pdf'];
    $pdf=新的FPDI();
    //迭代文件数组并合并
    foreach($files作为$file){
    $pageCount=$pdf->setSourceFile($file);
    对于($i=0;$i<$pageCount;$i++){
    $tpl=$pdf->importPage($i+1,'/MediaBox');
    $pdf->addPage();
    $pdf->useTemplate($tpl);
    }
    }
    //将pdf输出为文件(http://www.fpdf.org/en/doc/output.htm)
    $pdf->Output('F','merged.pdf');
    
    相关问题(顺便回答):@Webnet实际上,64%是可以的。我会说0-25%=失败,但我想这就是它的主观性。你可以使用命令行工具吗?你可以使用Zend Framework吗?我在哪里可以找到“pdftk-112-1i386.rpm”文件以及如何将其安装到服务器?我无法理解您的代码。请您解释更多详细信息?我也没有找到“setSourceFile”和“importPage”fpdf手册中的函数。我回去更详细地查看了我的解决方案。我希望这更有帮助。今天早上我写这篇文章时完全忘记了fdpi部分,它是我编写的一个相当复杂的PDF生成器的一小部分。@Christa小心FPDI只会解析某些PDF文件。我遇到了一个问题,其中FPDI不会解析v1.4以上的PDF文件,FPDI让我买他们的解析器来处理>v1.4…耶…你不觉得做$i=0和$i更好吗这基本上是有人实现了@Christa的答案(FPDF+FDPI),这很好:)谢谢!这也是d
        // array to hold list of PDF files to be merged
        $files = array("a.pdf", "b.pdf", "c.pdf");
        $pageCount = 0;
        // initiate FPDI
        $pdf = new FPDI();
    
        // iterate through the files
        foreach ($files AS $file) {
            // get the page count
            $pageCount = $pdf->setSourceFile($file);
            // iterate through all pages
            for ($pageNo = 1; $pageNo <= $pageCount; $pageNo++) {
                // import a page
                $templateId = $pdf->importPage($pageNo);
                // get the size of the imported page
                $size = $pdf->getTemplateSize($templateId);
    
                // create a page (landscape or portrait depending on the imported page size)
                if ($size['w'] > $size['h']) {
                    $pdf->AddPage('L', array($size['w'], $size['h']));
                } else {
                    $pdf->AddPage('P', array($size['w'], $size['h']));
                }
    
                // use the imported page
                $pdf->useTemplate($templateId);
    
                $pdf->SetFont('Helvetica');
                $pdf->SetXY(5, 5);
                $pdf->Write(8, 'Generated by FPDI');
            }
        }