Подтвердить что ты не робот

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

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

4b9b3361

Ответ 1

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

Ответ 2

Ниже приведена команда объединения 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);

Я забыл ссылку, откуда нашел ее, но она отлично работает.

Примечание: у вас должен быть gs (на linux и, вероятно, Mac) или Ghostscript (на windows), чтобы это работало.

Ответ 3

Я предлагаю PDFMerger с github.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

Ответ 4

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

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

Ответ 5

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

Ответ 6

Как принятый ответ, так и даже домашняя страница 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');

Ответ 7

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

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

Но тогда мы получили некоторые странные метаданные в выходных свойствах 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);

Ответ 8

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

Ответ 9

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

Ответ 10

Это сработало для меня в 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);
    

Ответ 11

Что мне нужно сделать, чтобы 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);

Ответ 12

Решение 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