Объединение PDF-файлов с помощью PHP

Моя концепция – на веб-сайте есть 10 файлов PDF. пользователь может выбрать некоторые PDF-файлы, и они выбирают merge для создания одного PDF-файла, который содержит выбранные страницы. Как я могу сделать это с помощью php?

Я сделал это раньше. У меня был pdf-файл, который я сгенерировал с помощью fpdf, и мне нужно было добавить к нему переменное количество 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 в изображение в другой PDF-файл. Он отлично работал для того, для чего мне это нужно.

Ниже приведена команда слияния php PDF.

 $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); 

Я забыл ссылку, откуда я ее нашел, но она работает нормально.

Я предлагаю PDFMerger из pdfmerger.codeplex.com , так легко, как:

 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 

Коды, используемые в PDFMerger, устарели в версии PHP5. Я разблокировал и исправил коды для работы с PHP 5. Вы можете захватить мою учетную запись github https://github.com/myokyawhtun/PDFMerger

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

Упрощенная версия ответа Чаухана

Не совсем понятно, почему и принятый ответ, и даже домашняя страница FDPI, похоже, дают неудачные или неполные примеры. Вот мой, который работает и его легко реализовать. Как и ожидалось, для него требуются библиотеки fpdf и fpdi:

 require('fpdf.php'); require('fpdi.php'); $files = ['doc1.pdf', 'doc2.pdf', 'doc3.pdf']; $pdf = new FPDI(); // iterate over array of files and merge foreach ($files as $file) { $pageCount = $pdf->setSourceFile($file); for ($i = 0; $i < $pageCount; $i++) { $tpl = $pdf->importPage($i + 1, '/MediaBox'); $pdf->addPage(); $pdf->useTemplate($tpl); } } // output the pdf as a file (http://www.fpdf.org/en/doc/output.htm) $pdf->Output('F','merged.pdf'); 

У меня была аналогичная проблема в моем программном обеспечении. Мы хотели объединить несколько файлов PDF в один PDF-файл и отправить его во внешнюю службу. Мы использовали решение FPDI, как показано в решении Christa .

Однако входной PDF-файл, который мы использовали, может быть в версии выше 1.7. Мы решили оценить коммерческое дополнение FPDI. Однако выяснилось, что некоторые из документов, отсканированных нашим офисным копиром, имели неверные индексы, которые разбили коммерческое дополнение FPDI. Поэтому мы решили использовать решение Ghostscript, как в ответе Чаухана .

Но тогда мы получили некоторые странные метаданные в выходных свойствах PDF.

Наконец, мы решили объединить два решения, чтобы объединить PDF-файлы и понизить их с помощью Ghostscript, но метаданные установлены 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 = new MergedPDF(); $pdf->setTitle($pdfTitle); $pdf->addDocumentPath($absolutePath1); $pdf->addDocumentPath($absolutePath2); $pdf->addDocumentPath($absolutePath3); $tempFileName = tempnam(sys_get_temp_dir(), 'merged'); $content = $pdf->Render(); file_put_contents($tempFileName, $content); 

Я пробовал аналогичную проблему и отлично работает, попробуйте. Он может обрабатывать различные ориентации между 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'); } } 

Это работало для меня в Windows

  1. скачать PDFtk бесплатно с https://www.pdflabs.com/tools/pdftk-the-pdf-toolkit/
  2. (PDFtk) в корень c:
  3. добавьте следующее в ваш php-код, где $ file1 – это местоположение и имя первого файла PDF, $ file2 – это местоположение и имя второго, а $ 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); 

Решение myokyawhtun работало лучше всего для меня (используя PHP 5.4)

Вы все равно получите сообщение об ошибке: я решил использовать следующее:

Строка 269 файла fpdf_tpl.php – изменила параметры функции на:

 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) { 

Я также сделал это же изменение в строке 898 файла fpdf.php

Я создал слой абстракции над 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; } 

Что я должен сделать, чтобы source.pdf с 2 страницами отображался / генерировался. «Pdf / Source.pdf» – 2 страницы, но отображается только одна страница.

Вот исходный код …

 require_once('pdf/fpdf/fpdf.php'); require_once('pdf/fpdi/fpdi.php'); $x34 = new FPDI(); $x34->AddPage(); $x34->setSourceFile("pdf/Source.pdf"); $x35 = $x34->importPage(1); $x34->useTemplate($x35, 0, 0, 200); $x34->SetFont('Arial'); $x34->SetFontSize(10.0);