PDF 파일을 PHP로 병합 [닫기]


83

내 개념은-웹 사이트에 10 개의 pdf 파일이 있습니다. 사용자는 일부 pdf 파일을 선택한 다음 병합을 선택하여 선택한 페이지를 포함하는 단일 pdf 파일을 만들 수 있습니다. PHP로 어떻게 할 수 있습니까?



3
@Webnet 실제로 64 %는 괜찮습니다. 나는 0-25 % = 실패라고 말하고 싶지만 그것이 주관적인 부분이라고 생각합니다
Sean Patrick Floyd

명령 줄 도구를 사용할 수 있습니까?
Pekka 2011 년

Zend Framework를 사용할 수 있습니까? stackoverflow.com/questions/4254218/…
Pekka 2011 년

"pdftk-112-1i386.rpm"파일은 어디에서 찾을 수 있으며 서버에 설치하는 방법은 무엇입니까?
Imrul.H 2011 년

답변:


28

나는 전에 이것을했다. 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를 이미지로 만들어 다른 pdf에 넣습니다. 내가 필요로하는 것에 대해 놀랍게도 잘 작동했습니다.


코드를 이해할 수 없습니다. 좀 더 자세히 설명해 주시겠습니까? 또한 fpdf 매뉴얼에서 "setSourceFile"및 "importPage"기능을 찾지 못했습니다.
Imrul.H 2011 년

돌아가서 내 솔루션을 좀 더 자세히 살펴 보았습니다. 이것이 더 도움이되기를 바랍니다. 나는 오늘 아침 내가 이것을 썼을 때 fdpi 부분을 완전히 잊었다. 내가 작성한 꽤 복잡한 PDF 생성기의 작은 부분이다.
Christa 2011 년

7
@Christa FPDI는 특정 PDF 파일 만 구문 분석합니다. FPDI가 v 1.4 이상의 PDF 파일을 구문 분석하지 않고 FPDI가 처리 할 구문 분석기를 구입하게 만드는 문제가 있습니다.> v1.4 ... yar ....
n0nag0n

$ i = 0 및 $ i <= $ pagecount를하는 것이 더 낫다고 생각하지 마십시오. 내가 생각하는 것을 읽는 것이 더 좋습니다. 좋은 예는 BTW, 정말 도움이
Nebulosar

126

아래는 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)가 설치되어 있어야합니다.


4
그것은 문제없이 FPDI 또는 기타로 외부 라이브러리를 설치하지 않고도 저에게 효과적이었습니다.
Memochipan 2013 년

4
이 솔루션은 저에게 가장 적합했습니다. 내 서버에 Ghostscript를 설치하는 것은 매우 쉬웠습니다. 그냥 "yum install ghostscript"였습니다. 그리고 스크립트가 완벽하게 작동했습니다
Theo Kouzelis 2013-04-24

1
나는 빈 pdf 페이지를 얻고있다 :(
itsazzad 2014 년

2
Ghostscript를 설치해야합니다. 그렇지 않으면 자동으로 실패합니다.
Pascal Klein

2
실제로 무엇을하는지 설명해야합니다. 실제로 작업을 수행하는 것은 실제로 PHP 방식이 아닙니다. PHP에서는 데이터 만 준비한 다음 실제 작업을 수행하는 쉘 스크립트를 실행합니다. 또한 대답에 포함해야합니다. gs (리눅스 및 Mac에서) 또는 Ghostscript (Windows에서)가 작동하도록 설치해야합니다. , 나는 그것을 설치할 필요가 없었습니다.
Vulgo Alias

39

나는 github.com 에서 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

3
이것은 기본적으로 @Christa의 답변 (FPDF + FDPI)에 대한 누군가의 구현입니다. :) 감사합니다!
Nahuel

5
또한 일부 PDF의 일부 압축 유형에서는 작동하지 않습니다.
Theo Kouzelis 2013

3
이것을 DOMPDF와 함께 사용하면 매력적으로 작동합니다. 감사합니다!
Matthew

1
"FPDF 오류 : 외부 참조 테이블을 찾을 수 없습니다."가 나타납니다. 그것에 대한 해결책이 있습니까?
Sameeraa4ever

1
작동하지만 가끔 아래에 오류가 표시됩니다 ... FPDF 오류 :이 문서 (samplepdfs / four.pdf)는 아마도 FPDI와 함께 제공되는 무료 파서에서 지원하지 않는 압축 기술을 사용하고 있습니다.
Nikhil

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

Chauhan의 대답의 단순화 된 버전


고스트 스크립트가 이미 설치되어 있어야합니다 있도록 설계 HostGator에 CentOS에 나를 위해이 가공 한 고급 서버 전용
마이크 볼 마르에게

너무 쉬웠 기 때문에 정답으로 표시되어야합니다. FPDF 및 FPDI로 고생하는 시간이 올바르게로드되지 않습니다. 당신은 내 생명을 구했습니다. 서버에 "imagemagick"(debian / ubuntu : apt install imagemagick)를 설치하기 만하면됩니다. 괜찮습니다. 건배!
Florian Doyen

9

받아 들여지는 대답과 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');

안녕하세요 @billynoah 저는 이것을 좋아하지만 풍경에서는 작동하지 않으며 첫 번째 페이지 만 병합하는 것 같습니다.
Geraldo Isaaks 2016 년

2
@GeraldoIsaaks-이후에 내 응용 프로그램에서 다중 페이지 문서에 대한 지원을 추가했습니다. 답변을 업데이트했습니다. 풍경 문제에 대해 잘 모르겠습니다. 저는 그런 문제를 겪지 않았습니다.
billynoah

FPDI 초창기부터 사용 가능한 예문에는 무엇이 있습니까?
Jan Slabon

@Setasign-나는 그것을 본 적이 없지만 공유해 주셔서 감사합니다.
billynoah

@billynoah 여기에 명확하고 업데이트 된 간단한 코드 예제에 감사드립니다. 시작했습니다. 나는 setasign 예제 ( setasign.com/products/fpdi/demos/concatenate-fake , 위의 주석에서 링크를 놓치기 쉽습니다) 의 코드를 더 많이 사용했습니다 . addPage 호출 내부의 논리로 인해 특정 연결된 페이지가 더 좋아 보입니다. 내가 그것을 테스트하지는 않았지만 아마도 세로 / 가로를 더 잘 처리 할 것입니다. 그러나 나는 검색으로 예를 찾지 못했고 당신의 대답을 볼 때까지 내가 관심이 있다는 것을 알지 못했습니다.
Anne Gunn

5

내 소프트웨어에서 비슷한 문제가 발생했습니다. 여러 PDF 파일을 하나의 PDF 파일로 병합하여 외부 서비스에 제출하려고했습니다. 우리는 Christa 의 솔루션에 표시된 것처럼 FPDI 솔루션을 사용하고 있습니다.

그러나 우리가 사용하고있는 입력 PDF는 1.7보다 높은 버전 일 수 있습니다. 우리는 FPDI 상용 애드온을 평가하기로 결정했습니다. 그러나 사무실 복사기로 스캔 한 문서 중 일부에 잘못된 색인이 포함되어있어 상업용 FPDI 추가 기능이 중단되었습니다. 그래서 우리는 Chauhan 의 대답 과 같이 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 = 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);

언급하자면 Windows 환경에서 동일한 코드를 사용했습니다. . 그리고하지만 매개 변수 "에서 프로그램 폴더를 넣어하는 것을 잊지 마세요$cmd = "\"C:\\Program Files\\gs\\gs9.20\\bin\\gswin64c.exe\" -q -dNOPAUSE -dBATCH -dCompatibilityLevel=1.4 -sDEVICE=pdfwrite -sOutputFile=[....your parameters...]" ;
프레데릭 클레

3

나는 비슷한 문제를 시도하고 잘 작동합니다. 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');
        }
    }

이것은 준다 Undefined index: w
senty

있는지 확인하십시오 당신은 FPDF가 제대로 구성되어
케빈 추이

나를위한 매개 변수는 $ size [ 'w'] 및 $ size [ 'h'] 대신 $ size [ 'width'] 및 $ size [ 'height']였습니다.
gorillagoat

0

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;
}

0

이것은 Windows에서 나를 위해 일했습니다.

  1. https://www.pdflabs.com/tools/pdftk-the-pdf-toolkit/ 에서 PDFtk를 무료로 다운로드 하십시오.
  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);
    

이것을 훨씬 더 깔끔하게 만드는 PHP 래퍼가 있습니다. github.com/mikehaertl/php-pdftk
Sean the Bean

참고 : PdfTK는 RHEL 7 또는 Cent OS 7
Ray

저에게는 다음과 같이 작동했습니다 . $command = "cmd /c C:\\pdftk\\bin\\pdftk.exe {$file1} {$file2} cat output {$new}";추가 cat 출력을 확인하십시오 . 참조 PDFtk 예
maxpower9000

-1

myokyawhtun의 솔루션이 나에게 가장 적합했습니다 (PHP 5.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 행에서도 이와 동일한 변경을 수행했습니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.