My concept is - there are 10 pdf files in a website. User can select some pdf files and then select merge to create a single pdf file which contains the selected pages. How can i do this with php?
-
Related question (answered btw): http://stackoverflow.com/questions/2713701/php-how-to-combine-merge-multiple-pdfs – Fran Verona Jan 25 '11 at 14:15
-
3@Webnet actually, 64% is ok. I'd say 0 - 25% = fail, but I guess that's where it gets subjective – Sean Patrick Floyd Jan 25 '11 at 14:29
-
Can you use a command line tool? – Pekka Jan 25 '11 at 14:34
-
Can you use Zend Framework? http://stackoverflow.com/questions/4254218/merging-2-pdf-with-zend-framework – Pekka Jan 25 '11 at 14:35
-
Where can i find "pdftk-112-1i386.rpm" file and how to install it to the server? – Imrul.H Jan 25 '11 at 17:21
10 Answers
Below is the php PDF merge command.
$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);
I forgot the link from where I found it, but it works fine.
Note: You should have gs (on linux and probably Mac), or Ghostscript (on windows) installed for this to work.

- 3,977
- 3
- 24
- 30
-
4It worked for me without problems and without installing external libraries as FPDI or others. – Memochipan Jan 30 '13 at 21:57
-
4This solution worked best for me. It was very easy to install Ghostscript on my server. It was just "yum install ghostscript". And your script worked perfectly – Theo Kouzelis Apr 24 '13 at 10:02
-
This merged my PDF's but unfortunately stripped all the data from the fillable fields and also broke the fields themselves. – Matt Jul 15 '14 at 03:47
-
1
-
2016 here, this thing still works like a charm. For people having a white page, you need to give the full adress on your file (name1.pdf -> blabla/n/qkjsdfgh/name1.pdf) – David Aclub Mar 18 '16 at 16:14
-
It is working very fine. But I am getting and problem. In my pdf I have bullets using • but when I merge using command they converted into square.Please help if any one can – Bharat Maheshwari May 31 '16 at 14:15
-
I have two pdf and both are open properly but when combine using your coding and that time I am getting blank page Can you please help me in the same? – Bhavin Solanki Dec 19 '16 at 11:25
-
How long does this take, lets say you have ten 1,000 page documents and want to merge them, would this take 2 seconds or 2 minutes? – Joel Davis May 01 '17 at 00:30
-
2017 and it works kinda. I am finding that Macs have better luck running the script. Windows based machines are generating white pages but only sometimes. What might be causing this? – jeynon Aug 09 '17 at 16:49
-
3
-
How I do this with base64encoded sting. it is not saved on the disc. – Nishad Up Apr 19 '18 at 08:28
-
1I am getting this message **** Unable to open the initial device, quitting. – Nishad Up Apr 19 '18 at 08:42
-
4You should explain what it actually does. It actually is not really a php way to do the task, in php you only prepare data and then you execute a shell script, which does the actual task. also you should include in your answer, that gs (on linux and probably Mac), or Ghostscript (on windows) should be installed for this to work.. Still i quite like this solution, as gs is included in Ubuntu by default i think, i did not have to install it. – An Capone May 14 '18 at 15:51
-
1Also i think this could be a link to original solution: www.codeexpertz.com.prox.science/blog/php/php-merge-multiple-pdf-files-single-pdfresolving-timeout-error – An Capone May 14 '18 at 15:59
-
Script works, just a suggestion, Instead of `foreach` loop you may use `implode` function of PHP, it will save one loop – Akshay Khale May 31 '18 at 12:24
-
-
if you set all the path as absolute path and you have ghostscript installed. this works like a charm – TheDevWay Jan 20 '20 at 10:37
-
@NishadUp brother have you solved that issues saying "**** Unable to open the initial device, quitting." . please let me know i am getting guide me how to solve it? – Ajay Kumar Oad Oct 18 '20 at 17:17
-
Worked like a charm, struggling since hours with FPDI not working. Nedd to install imagemagick on linux tho, but still a better way to do that installing third party php libs... – Florian Doyen Dec 09 '20 at 12:02
i suggest PDFMerger from github.com, so easy like ::
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

- 10,422
- 29
- 111
- 186

- 6,395
- 5
- 33
- 37
-
3This is basically someone's implementation of @Christa's answer (FPDF+FDPI), which is great :) Thanks! – Nahuel Jan 30 '13 at 13:04
-
It does work on some PDF's really well, but some of the code is now deprecated. – Theo Kouzelis Apr 24 '13 at 09:41
-
9Its also doesn't work with some types of compression on some PDF's. – Theo Kouzelis Apr 24 '13 at 10:04
-
3
-
1I am getting "FPDF error: Unable to find xref table." any solution for that? – Sameeraa4ever Jun 11 '15 at 01:17
-
@Sameeraa4ever google it, the solution* is on the first result :P – AgelessEssence Jun 12 '15 at 08:29
-
1It works but sometime shows error below... FPDF error: This document (samplepdfs/four.pdf) probably uses a compression technique which is not supported by the free parser shipped with FPDI. – Nikhil Jul 19 '16 at 12:56
-
For PDFs of version 1.5 or higher you need a paid version of the fpdi library used by this solution (per the error cited by @Nikhil ) – Stephen R Oct 17 '18 at 20:03
-
The original PDFMerger project (not the clone linked above) appears to have moved away from the commercial fpdi library: https://github.com/myokyawhtun/PDFMerger – Stephen R Oct 17 '18 at 20:53
-
this does not work for images, if you have picture in your sources, it wont get copied – Sahib Khan Dec 14 '19 at 20:39
-
1
I've done this before. I had a pdf that I generated with fpdf, and I needed to add on a variable amount of PDFs to it.
So I already had an fpdf object and page set up (http://www.fpdf.org/) And I used fpdi to import the files (http://www.setasign.de/products/pdf-php-solutions/fpdi/) FDPI is added by extending the PDF class:
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);
}
This basically makes each pdf into an image to put into your other pdf. It worked amazingly well for what I needed it for.

- 485
- 4
- 4
-
1I cannot understand your code. can you please explain some more detail? I also did not find "setSourceFile" and "importPage" functions in fpdf manual. – Imrul.H Jan 25 '11 at 18:34
-
I went back and looked at my solution a little more in detail. I hope this is more helpful. I completely forgot about the fdpi part this morning when I wrote this, its one small part of a pretty complicated PDF generator I wrote. – Christa Jan 25 '11 at 19:01
-
10@Christa Beware that FPDI will only parse certain PDF files. I'm running into a problem where FPDI won't parse PDF files above v 1.4 and FPDI is making me buy their parser to handle > v1.4... yar.... – n0nag0n Jul 06 '12 at 02:55
-
Don't you think it's better to do $i = 0 and $i <= $pagecount. It makes it better to read i think. Great example btw, really helped me – Nebulosar Jun 22 '17 at 07:53
-
`This basically makes each pdf into an image to put into your other pdf.` that is not quite true, its not converting the pdf into an image. Text is still selectable. – Adam Oct 06 '22 at 04:45
$cmd = "gs -q -dNOPAUSE -dBATCH -sDEVICE=pdfwrite -sOutputFile=".$new." ".implode(" ", $files);
shell_exec($cmd);
A simplified version of Chauhan's answer

- 346
- 3
- 5
-
This worked fine for me on hostgator centos dedicated server so ghostscript must already be installed – Mike Volmar Aug 28 '19 at 18:52
-
Should be marked as a correct answer too, because it was so damn EASY. Hours struggling with FPDF and FPDI not loading correctly. You saved my life. Just need to install "imagemagick" (on debian/ubuntu : apt install imagemagick) on the server and it's ok. Cheers ! – Florian Doyen Dec 09 '20 at 12:01
Both the accepted answer and even the FDPI homepage seem to give botched or incomplete examples. Here's mine which works and is easy to implement. As expected it requires fpdf and fpdi libraries:
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');

- 21,377
- 10
- 81
- 108
-
Hi @billynoah I like this but it does not work on landscape and seems to only merge the 1st pages. – Geraldo Isaaks Sep 22 '16 at 10:09
-
2@GeraldoIsaaks - I subsequently added support for multipage documents in my own application. I've updated the answer. Not sure about landscape issues - I haven't run into that. – But those new buttons though.. Sep 22 '16 at 12:38
-
What's butched on [this](https://www.setasign.com/products/fpdi/demos/concatenate-fake/) examle which is available since the early days of FPDI? – Jan Slabon Sep 22 '16 at 12:47
-
@Setasign - I've never seen that but thanks for sharing. – But those new buttons though.. Sep 23 '16 at 02:08
-
@billynoah Thanks for the clear and updated simple code example here in SO. It got me started. I ended up using more of the code from the setasign example (https://www.setasign.com/products/fpdi/demos/concatenate-fake/, link is easy to miss in comment above). Their logic inside the addPage call made my particular concatenated pages look better. Probably also handles portrait/landscape better although I didn't test that. But I didn't find the example with searches and didn't know I was interested till I saw your answer. – Anne Gunn Apr 11 '17 at 23:04
I've had similar problem in my software. We've wanted to merge several PDF files into one PDF file and submit it to an outer service. We've been using the FPDI solution as shown in Christa's solution.
However, the input PDF's we've been using could be in version higher than 1.7. We've decided to evaluate the FPDI commercial add-on. However, it turned out that some of the documents scanned by our office copier were having malformed indexes, which crashed the commercial FPDI add-on. So we've decided to use Ghostscript solution as in Chauhan's answer.
But then we got some strange metadata in the output PDF properties.
Finally we've decided to join two solutions to get PDF's merged and downgraded by Ghostscript, but the metadata is set by FPDI. We don't know yet how it would work with some advanced formatted pdfs, but for scans we use it works just fine. Here's our class excerpt:
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;
}
}
The usage of this class is as follows:
$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);

- 309
- 3
- 3
-
Just to mention, That I used the same code on Windows env. and don't forget to put program folder in " but not the parameters. `$cmd = "\"C:\\Program Files\\gs\\gs9.20\\bin\\gswin64c.exe\" -q -dNOPAUSE -dBATCH -dCompatibilityLevel=1.4 -sDEVICE=pdfwrite -sOutputFile=[....your parameters...]" ; ` – Frédéric Klee Nov 04 '16 at 08:40
I have tried similar issue and works fine, try it. It can handle different orientations between PDFs.
// 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');
}
}

- 147
- 1
- 7
-
-
-
the parameters for me were $size['width'] and $size['height'] instead of $size['w'] and $size['h'] – gorillagoat Mar 15 '19 at 23:38
This worked for me on Windows
- download PDFtk free from https://www.pdflabs.com/tools/pdftk-the-pdf-toolkit/
- drop folder (PDFtk) into the root of c:
add the following to your php code where $file1 is the location and name of the first PDF file, $file2 is the location and name of the second and $newfile is the location and name of the destination file
$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);

- 10,112
- 5
- 45
- 64

- 44
- 2
-
1There is a PHP wrapper that makes this much cleaner. See https://github.com/mikehaertl/php-pdftk – Sean the Bean May 18 '16 at 15:52
-
-
For me it only worked like this: `$command = "cmd /c C:\\pdftk\\bin\\pdftk.exe {$file1} {$file2} cat output {$new}";` Notice the additional **cat output**. See [PDFtk examples](https://www.pdflabs.com/docs/pdftk-cli-examples/) – maxpower9000 Jun 24 '16 at 07:54
I created an abstraction layer over FPDI (might accommodate other engines). I published it as a Symfony2 bundle depending on a library, and as the library itself.
usage:
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;
}

- 2,002
- 2
- 26
- 28
myokyawhtun's solution worked best for me (using PHP 5.4)
You will still get an error though - I resolved using the following:
Line 269 of fpdf_tpl.php - changed the function parameters to:
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) {
I also made this same change on line 898 of fpdf.php

- 159
- 2
- 5