PDFファイルをPHPとマージする[クローズ]


83

私のコンセプトは-ウェブサイトには10​​個のPDFファイルがあります。ユーザーはいくつかのPDFファイルを選択してから、マージを選択して、選択したページを含む単一のPDFファイルを作成できます。PHPでこれを行うにはどうすればよいですか?


関連する質問(ところで回答済み):stackoverflow.com/questions/2713701/…–
Fran Verona

3
@Webnet実際には、64%は問題ありません。
ショーンパトリックフロイド

コマンドラインツールを使用できますか?
ペッカ2011年

Zend Frameworkを使用できますか?stackoverflow.com/questions/4254218/…–
Pekka

「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ジェネレーターの小さな部分です。
クリスタ2011年

6
@ChristaFPDIは特定のPDFファイルのみを解析することに注意してください。FPDIがv1.4より上のPDFファイルを解析せず、FPDIが> v1.4を処理するためにパーサーを購入させているという問題に直面しています...
yar

$ i = 0および$ i <= $ pagecountを実行する方が良いと思いませんか。読むほうがいいと思います。素晴らしい例ところで、本当に助けてくれました
Nebulosar 2017年

123

以下は、phpPDFマージコマンドです。

$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などの外部ライブラリをインストールすることなく機能しました。
メモチパン2013年

4
このソリューションは私にとって最適でした。サーバーにGhostscriptをインストールするのはとても簡単でした。それはただの「yuminstallghostscript」でした。そして、あなたのスクリプトは完璧に機能しました
Theo Kouzelis 2013

1
空白のPDFページが表示されます:(
itsazzad 2014

2
Ghostscriptをインストールする必要があります。インストールしないと、サイレントに失敗します。
パスカルクライン

2
あなたはそれが実際に何をするのかを説明するべきです。これは実際にはタスクを実行するためのphpの方法ではありません。phpではデータを準備するだけで、実際のタスクを実行するシェルスクリプトを実行します。また、これを機能させるには、gs(LinuxおよびおそらくMac)またはGhostscript(Windows)をインストールする必要があることを回答に含める必要があります。gsはデフォルトでUbuntuに含まれているため、このソリューションは非常に気に入っています。 、私はそれをインストールする必要はありませんでした。
Vulgo Alias 2018

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)を実装したもので、すばらしいです:)ありがとう!
ナウエル

5
また、一部のPDFの一部の種類の圧縮では機能しません。
Theo Kouzelis 2013

3
これをDOMPDFで使用すると、魅力的に機能します。ありがとうございます。
マシュー

1
「FPDFエラー:外部参照テーブルが見つかりません」というメッセージが表示されます。そのための解決策はありますか?
sameeraa4ever 2015年

1
動作しますが、以下のエラーが表示される場合があります... FPDFエラー:このドキュメント(samplepdfs / four.pdf)は、FPDIに付属の無料のパーサーでサポートされていない圧縮技術を使用している可能性があります。
Nikhil 2016

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

チャウハンの答えの簡略版


これはhostgatorcentos専用サーバーでうまく機能したので、ghostscriptがすでにインストールされている必要があります
MikeVolmar19年

9

受け入れられた回答とFDPIホームページの両方で、失敗した例や不完全な例が示されているようです。これが機能し、実装が簡単な私のものです。予想どおり、fpdfおよびfpdiライブラリが必要です。

  • FPDF:http://www.fpdf.org/en/download.php
  • FPDI:https://www.setasign.com/products/fpdi/downloads
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-その後、自分のアプリケーションで複数ページのドキュメントのサポートを追加しました。答えを更新しました。景観の問題についてはよくわかりません-私はそれに遭遇していません。
ビリノア2016

FPDIの初期から利用できるこの例には何がありますか?
Jan Slabon 2016

@ Setasign-私はそれを見たことがありませんが、共有してくれてありがとう。
ビリノア2016

@billynoahここSOの明確で更新された簡単なコード例をありがとう。それは私を始めました。私はsetasignの例(setasign.com/products/fpdi/demos/concatenate-fake、上記のコメントでリンクを見逃しがちです)のコードをもっと使用することになりました。addPage呼び出し内のロジックにより、特定の連結ページの見栄えが良くなりました。私はそれをテストしませんでしたが、おそらくポートレート/風景もよりよく処理します。しかし、私は検索で例を見つけられず、あなたの答えを見るまで私が興味を持っていることを知りませんでした。
アンガン

5

私のソフトウェアでも同様の問題が発生しました。複数のPDFファイルを1つのPDFファイルにマージして、外部サービスに送信したいと考えていました。Christaのソリューションに示されているように、FPDIソリューションを使用してきました。

ただし、使用している入力PDFは、1.7より古いバージョンである可能性があります。FPDI商用アドオンを評価することにしました。しかし、私たちのオフィスのコピー機によってスキャンされたドキュメントのいくつかが不正な形式のインデックスを持っていたことが判明し、それが商用FPDIアドオンをクラッシュさせました。そこで、Chauhanの回答のようにGhostscriptソリューションを使用することにしました。

しかし、出力PDFプロパティに奇妙なメタデータが含まれています。

最後に、GhostscriptによってPDFをマージおよびダウングレードするために、2つのソリューションを結合することにしましたが、メタデータは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...]" ;
FrédéricKlee 2016年

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
センチメント2018年

あなたが適切に設定さFPDF持たせる
ケビン・チュイ

私のためのパラメータは$サイズ[「幅」]と$サイズの代わりに$サイズの[「高さ」] [「W」]と$サイズ[「H」]だった
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は2番目のファイルの場所と名前、$ 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はRHEL7またはCentOS 7では機能しません
Ray

私にとっては、次のようにしか機能しませんでした。$command = "cmd /c C:\\pdftk\\bin\\pdftk.exe {$file1} {$file2} cat output {$new}";追加のcat出力に注意してください。PDFtkの例を
maxpower9000 2016年

-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.