11 ответов:
Я уже делал это раньше. У меня был 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 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);Я забыл ссылку, откуда я ее нашел, но она отлично работает.
предлагаю 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
$cmd = "gs -q -dNOPAUSE -dBATCH -sDEVICE=pdfwrite -sOutputFile=".$new." ".implode(" ", $files); shell_exec($cmd);упрощенная версия ответа Чаухана
коды, используемые в PDFMerger, устарели в версии PHP5. Я разветвил и исправил коды для работы с PHP 5. Вы можете захватить мой аккаунт githubhttps://github.com/myokyawhtun/PDFMerger
у меня была аналогичная проблема в моем программном обеспечении. Мы хотели объединить несколько PDF-файлов в один PDF-файл и отправить его во внешнюю службу. Мы использовали решение FPDI, как показано в Криста'ы.
однако входные 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);
Не совсем уверен, почему и принятый ответ, и даже домашняя страница 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-файлами.
// 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
- скачать PDFtk бесплатно сhttps://www.pdflabs.com/tools/pdftk-the-pdf-toolkit/
- drop folder (PDFtk) в корень c:
добавьте следующее в свой 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; }
Comments