How to Merge Two PDF Files into One in Java

How to merge two PDF files into one in Java?

Why not use the PDFMergerUtility of pdfbox?

PDFMergerUtility ut = new PDFMergerUtility();
ut.addSource(...);
ut.addSource(...);
ut.addSource(...);
ut.setDestinationFileName(...);
ut.mergeDocuments();

Merge pdf files within folder java

Here is a working example. I have used ITEXT

Dependencies :

<dependency>
<groupId>com.itextpdf</groupId>
<artifactId>itextpdf</artifactId>
<version>5.5.10</version>
</dependency>

import com.itextpdf.text.Document;
import com.itextpdf.text.DocumentException;
import com.itextpdf.text.pdf.PdfCopy;
import com.itextpdf.text.pdf.PdfReader;
import com.itextpdf.text.pdf.PdfSmartCopy;

import java.io.File;
import java.io.FileOutputStream;
import java.io.FilenameFilter;
import java.io.IOException;
import java.util.List;

/**
* Created by RGOVIND on 11/7/2016.
*/
public class MergePDF {
static public void main(String[] args) throws Exception{
mergePDF("C:\\XX\\PDF","mergedFile.pdf");
}
public static void mergePDF(String directory, String targetFile) throws DocumentException, IOException {
File dir = new File(directory);
File[] filesToMerge = dir.listFiles(new FilenameFilter() {
public boolean accept(File file, String fileName) {
//System.out.println(fileName);
return fileName.endsWith(".pdf");
}
});
Document document = new Document();
FileOutputStream outputStream = new FileOutputStream("C:\\DevelopmentTools\\PDF\\"+targetFile);
PdfCopy copy = new PdfSmartCopy(document, outputStream);
document.open();

for (File inFile : filesToMerge) {
System.out.println(inFile.getCanonicalPath());
PdfReader reader = new PdfReader(inFile.getCanonicalPath());
copy.addDocument(reader);
reader.close();
}
document.close();
}
}

merge many pdf files into one pdf files in web application java

There are numerous errors in your code:

Only write to the response output stream what you want to return to the browser

Your code writes a wild collection of data to the response output stream:

ServletOutputStream servletOutPutStream = response.getOutputStream();;
[...]
for(byte[] imageList:imageMap)
{
[...]
byteArrayOutputStream.writeTo(response.getOutputStream());
[...]
}
[...]
PdfWriter writer = PdfWriter.getInstance(document, response.getOutputStream());
[... merge PDFs into the writer]

servletOutPutStream.flush();
document.close();

servletOutPutStream.close();

This results in many copies of the imageMap elements to be written there and the merged file only to be added thereafter.

What do you expect the browser to do, ignore all the leading source PDF copies until finally the merged PDF appears?

Thus, please only write the merged PDF to the response output stream.

Don't write a wrong content length

It is a good idea to write the content length to the response... but only if you use the correct value!

In your code you write a content length:

response.setContentLength(byteArrayOutputStream.size());

but the byteArrayOutputStream at this time only contains a wild mix of copies of the source PDFs and not yet the final merged PDF. Thus, this will only serve to confuse the browser even more.

Thus, please do not add false headers to the response.

Don't mangle your input data

In the loop

for(byte[] imageList:imageMap)
{
System.out.println(imageList.toString()+" "+imageList.length);

byteArrayOutputStream.write(imageList);

byteArrayOutputStream.writeTo(response.getOutputStream());

is = new ByteArrayInputStream(byteArrayOutputStream.toByteArray());
inputPdfList.add(is);
}

you take byte arrays which I assume contain a single source PDF each, pollute the response output stream with them (as mentioned before), and create a collection of input streams where the first one contains the first source PDF, the second one contains the concatenation of the first two source PDFs, the third one the concatenation of the first three source PDFs, etc...

Because you never reset or re-instantiate the byteArrayOutputStream, it only gets bigger and bigger.

Thus, please start or end loops like this with a reset of the byteArrayOutputStream.

(Actually you don't need that loop at all, the PdfReader has a constructor which can immediately take a byte[], no need to wrap it in a byte stream.)

Don't merge PDFs using a plain PdfWriter, use a PdfCopy

You merge the PDFs using a PdfWriter / getImportedPage / addTemplate approach. There are dozens of questions and answer on stack overflow (many of them answered by iText developers) explaining that this usually is a bad idea and that you should use PdfCopy.

Thus, please make use of the many good answers which already exist on this topic here and use PdfCopy for merging.

Don't flush or close streams only because you can

You finalize the response output by closing numerous streams:

//Close document and outputStream.
servletOutPutStream.flush();
outputStream.flush();
document.close();
outputStream.close();

servletOutPutStream.close();

I have not seen a line in which you declared or set that outputStream variable, but even if it contained the response output stream, there is no need to close that because you already close it in the servletOutPutStream variable.

Thus, please remove unnecessary calls like this.

Java - How to merge multiple documents (With Multiple file formats with file convert) to a single PDF?

Answering to My Own question to Benefit another person.
In order to Convert Files with extensions docx , xlsx , pptx) Used
Spire.Office for Java (Free Evaluation version available)

Also I tried aspose cells libray as well (Free Evaluation available) to convert xlsx to PDF as well. Both Libraries worked fine and hassle free , But all libraries were not free.

Then Merged all the PDF Files using ITEXT Library.
If Someone is having a better alternative answer , kindly share.

For multiple files merge, you can refer This Example

How merge and rotate two pdf pages to one page itext

Merge:

public void mergeTwoPagesIntoOne(String originalPdfFile, String outputPdfFile) throws IOException, DocumentException {
PdfReader reader = new PdfReader(originalPdfFile);
Document doc = new Document(new RectangleReadOnly(842f, 595f), 0, 0, 0, 0);
PdfWriter writer = PdfWriter.getInstance(doc, new FileOutputStream(outputPdfFile));
doc.open();
int totalPages = reader.getNumberOfPages();
for (int i = 1; i <= totalPages; i = i + 2) {
doc.newPage();
PdfContentByte cb = writer.getDirectContent();
PdfImportedPage page = writer.getImportedPage(reader, i); // page #1

float documentWidth = doc.getPageSize().getWidth() / 2;
float documentHeight = doc.getPageSize().getHeight();
if (i > 1)
documentHeight = documentHeight - 50f;

float pageWidth = page.getWidth();
float pageHeight = page.getHeight();

float widthScale = documentWidth / pageWidth;
float heightScale = documentHeight / pageHeight;
float scale = Math.min(widthScale, heightScale);

float offsetX = (documentWidth - (pageWidth * scale)) / 2;
float offsetY = 0f;

cb.addTemplate(page, scale, 0, 0, scale, offsetX, offsetY);

if (i+1 <= totalPages) {
PdfImportedPage page2 = writer.getImportedPage(reader, i+1); // page #2

pageWidth = page.getWidth();
pageHeight = page.getHeight();

widthScale = documentWidth / pageWidth;
heightScale = documentHeight / pageHeight;
scale = Math.min(widthScale, heightScale);

offsetX = ((documentWidth - (pageWidth * scale)) / 2) + documentWidth;
cb.addTemplate(page2, scale, 0, 0, scale, offsetX, offsetY);
}
}
doc.close();
}

Rotate:

    public void rotatePdf(String originalPdfFile, String outputPdfFile, int degrees) throws IOException, DocumentException {
PdfReader reader = new PdfReader(originalPdfFile);
for (int i = 1; i <= reader.getNumberOfPages(); i++) {
PdfDictionary dictionary = reader.getPageN(i);
dictionary.put(PdfName.ROTATE, new PdfNumber(degrees));
}
PdfStamper stamper = new PdfStamper(reader, new FileOutputStream(outputPdfFile));
stamper.close();
reader.close();
}


Related Topics



Leave a reply



Submit