This question already has answers here:
Merge pdf documents of different width using iText
(2 answers)
Closed 7 years ago.
I am encountering an issue while merging two PDFs generated out of IText.
Code snippet of PDF Creation:
Document configuration is as below:
iText_xls_2_pdf = new Document(PageSize.A4.rotate(),10,0,30,0);
Using this configuration 2 PDFs are created.
After creation of these PDFs, they need to be merged as single pdf.
Below code is used to merge the PDFs:
Document document = new Document(PageSize.A4.rotate(),10,0,30,0);
try {
List<InputStream> pdfs = streamOfPDFFiles;
List<PdfReader> readers = new ArrayList<PdfReader>();
int totalPages = 0;
Iterator<InputStream> iteratorPDFs = pdfs.iterator();
// Create Readers for the pdfs.
while (iteratorPDFs.hasNext()) {
InputStream pdf = iteratorPDFs.next();
PdfReader pdfReader = new PdfReader(pdf);
readers.add(pdfReader);
totalPages += pdfReader.getNumberOfPages();
}
// Create a writer for the outputstream
PdfWriter writer = PdfWriter.getInstance(document, outputStream);
document.open();
BaseFont bf = BaseFont.createFont(BaseFont.HELVETICA,
BaseFont.CP1252, BaseFont.NOT_EMBEDDED);
PdfContentByte cb = writer.getDirectContent(); // Holds the PDF
// data
PdfImportedPage page;
int currentPageNumber = 0;
int pageOfCurrentReaderPDF = 0;
Iterator<PdfReader> iteratorPDFReader = readers.iterator();
// Loop through the PDF files and add to the output.
while (iteratorPDFReader.hasNext()) {
PdfReader pdfReader = iteratorPDFReader.next();
// Create a new page in the target for each source page.
while (pageOfCurrentReaderPDF < pdfReader.getNumberOfPages()) {
document.newPage();
pageOfCurrentReaderPDF++;
currentPageNumber++;
page = writer.getImportedPage(pdfReader,
pageOfCurrentReaderPDF);
cb.addTemplate(page, 0, 0);
// Code for pagination.
if (paginate) {
cb.beginText();
cb.setFontAndSize(bf, 9);
cb.showTextAligned(PdfContentByte.ALIGN_CENTER, ""
+ currentPageNumber + " of " + totalPages, 520,
5, 0);
cb.endText();
}
}
pageOfCurrentReaderPDF = 0;
}
outputStream.flush();
document.close();
outputStream.close();
} catch (Exception e) {
e.printStackTrace();
} finally {
if (document.isOpen())
document.close();
try {
if (outputStream != null)
outputStream.close();
} catch (IOException ioe) {
ioe.printStackTrace();
}
}
This creates the merged PDF. but Because I have used .rotate in Document configuration, Merged pdf comes in landscape format. How could I avoid this.
Please take a look at table 6.1 in chapter 6 of my book, you'll find out that using PdfWriter to merge documents is not done. If you want to merge documents, you need to use PdfCopy.
For an example, see for instance these questions:
How to do pdf writing and copying at once?
put page number when create PDF with iTextSharp
Edit DirectContent of iTextSharp PdfSmartCopy class
...
(As you can see, this question has been answered many times before...)
An example:
PdfReader reader1 = new PdfReader(file1);
PdfReader reader2 = new PdfReader(file2);
Document document = new Document();
FileOutputStream fos = new FileOutputStream();
PdfCopy copy = new PdfCopy(document, fs);
document.open();
PdfImportedPage page;
PdfCopy.PageStamp stamp;
Phrase phrase;
BaseFont bf = BaseFont.createFont();
Font font = new Font(bf, 9);
int n = reader1.getNumberOfPages();
for (int i = 1; i <= reader1.getNumberOfPages(); i++) {
page = copy.getImportedPage(reader1, i);
stamp = copy.createPageStamp(page);
phrase = new Phrase("page " + i, font);
ColumnText.showTextAligned(stamp.getOverContent(), Element.ALIGN_CENTER, phrase, 520, 5, 0);
stamp.alterContents();
copy.addPage(page);
}
for (int i = 1; i <= reader2.getNumberOfPages(); i++) {
page = copy.getImportedPage(reader2, i);
stamp = copy.createPageStamp(page);
phrase = new Phrase("page " + (n + i), font);
ColumnText.showTextAligned(stamp.getOverContent(), Element.ALIGN_CENTER, phrase, 520, 5, 0);
stamp.alterContents();
copy.addPage(page);
}
document.close();
reader1.close();
reader2.close();
Related
I have code to merge between 2 pdf files using the library OpenPDF like this
public byte[] mergePDF(byte[] pdf1, byte[] pdf2) throws IOException {
ByteArrayOutputStream os = new ByteArrayOutputStream();
Document document = new Document();
PdfWriter writer;
try {
writer = PdfWriter.getInstance(document, os);
} catch (DocumentException e) {
throw new IllegalStateException(e);
}
document.open();
PdfContentByte cb = writer.getDirectContent();
PdfReader pdfReader1 = new PdfReader(pdf1);
PdfReader pdfReader2 = new PdfReader(pdf2);
for (int i = 0; i < pdfReader1.getNumberOfPages(); i++) {
PdfImportedPage page = writer.getImportedPage(pdfReader1, i + 1);
document.setPageSize(pdfReader1.getPageSize(i + 1));
document.newPage();
cb.addTemplate(page, 0, 0);
}
for (int i = 0; i < pdfReader2.getNumberOfPages(); i++) {
PdfImportedPage page = writer.getImportedPage(pdfReader2, i + 1);
document.setPageSize(pdfReader2.getPageSize(i + 1));
document.newPage();
cb.addTemplate(page, 0, 0);
}
document.close();
return os.toByteArray();
}
Merged PDF generated showing a blank page from on Page come from the second pdf but it showing when open with adobe acrobat, firefox, and ubuntu document viewer. Does anyone know what issue? or any missing configuration that needs to be set in my code?
I am using itext library to merge multiple pdfs, I am able to merge multiple pdfs but if pdf contain scan pages then i don't want to add it in merged PDF, Does it possible to check scan pages using itext?.
I am using Following code to merge pdf.
Document PDFJoinInJava = new Document();
PdfCopy PDFCombiner = new PdfCopy(PDFJoinInJava, outputStream);
PdfCopy.PageStamp stamp;
PDFJoinInJava.open();
PdfReader ReadInputPDF;
List<InputStream> pdfs = streamOfPDFFiles;
List<PdfReader> readers = new ArrayList<PdfReader>();
int totalPages = 0;
Iterator<InputStream> iteratorPDFs = pdfs.iterator();
for (; iteratorPDFs.hasNext(); pdfCounter++) {
InputStream pdf = iteratorPDFs.next();
PdfReader pdfReader = new PdfReader(pdf);
readers.add(pdfReader);
totalPages += pdfReader.getNumberOfPages();
pdf.close();
}
int number_of_pages;
int currentPageNumber = 0;
int pageOfCurrentReaderPDF = 0;
Iterator<PdfReader> iteratorPDFReader = readers.iterator();
PdfImportedPage page;
// Loop through the PDF files and add to the output.
int count = 1;
while (iteratorPDFReader.hasNext()) {
PdfReader pdfReader = iteratorPDFReader.next();
count++;
number_of_pages = pdfReader.getNumberOfPages();
// Create a new page in the target for each source page.
for (int pageNum = 0; pageNum < number_of_pages;) {
currentPageNumber++;
pageOfCurrentReaderPDF++;
page = PDFCombiner.getImportedPage(pdfReader, ++pageNum);
ColumnText.showTextAligned(stamp.getUnderContent(),
Element.ALIGN_RIGHT, new Phrase(String
.format("%d", currentPageNumber),new Font(FontFamily.TIMES_ROMAN,3)),
50, 50, 0);
stamp.alterContents();
PDFCombiner.addPage(page);
}
}
PDFJoinInJava.close();
If you like to find whether pdf file is generated by iText or not then you have to try following code:
File file = new File("/Demo.pdf");
Scanner input = new Scanner(new FileReader(file));
while (input.hasNextLine()) {
final String checkline = input.nextLine();
if(checkline.contains("Producer(iText")) {
// a match found!!!!!!
System.out.println(file.getName()+" is generated by iText........ :):) ");
break;
}
}
I have the following problem when printing the pdf file after merge, the pdf documents get cut off.
Sometimes this happens because the documents aren't 8.5 x 11
they might be like 11 x 17.
Can we make it detect the page size and then use that same page size for those documents?
Or, if not, is it possible to have it fit to page?
Following is the code:
package com.sumit.program;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import com.itextpdf.text.Document;
import com.itextpdf.text.PageSize;
import com.itextpdf.text.Rectangle;
import com.itextpdf.text.pdf.BaseFont;
import com.itextpdf.text.pdf.PdfContentByte;
import com.itextpdf.text.pdf.PdfImportedPage;
import com.itextpdf.text.pdf.PdfReader;
import com.itextpdf.text.pdf.PdfWriter;
public class MergePdf {
public static void main(String[] args) {
try {
List<InputStream> pdfs = new ArrayList<InputStream>();
pdfs.add(new FileInputStream("C:\\Documents and Settings\\Sumit\\Desktop\\NewEcnProject\\Document1.pdf"));
pdfs.add(new FileInputStream("C:\\Documents and Settings\\Sumit\\Desktop\\NewEcnProject\\Landscape.pdf"));
OutputStream output = new FileOutputStream("C:\\Documents and Settings\\Sumit\\Desktop\\NewEcnProject\\merge1.pdf");
MergePdf.concatPDFs(pdfs, output, true);
} catch (Exception e) {
e.printStackTrace();
}
}
public static void concatPDFs(List<InputStream> streamOfPDFFiles,
OutputStream outputStream, boolean paginate) {
Document document = new Document();
try {
List<InputStream> pdfs = streamOfPDFFiles;
List<PdfReader> readers = new ArrayList<PdfReader>();
int totalPages = 0;
Iterator<InputStream> iteratorPDFs = pdfs.iterator();
// Create Readers for the pdfs.
int i=1;
while (iteratorPDFs.hasNext()) {
InputStream pdf = iteratorPDFs.next();
PdfReader pdfReader = new PdfReader(pdf);
System.out.println("Page size is "+pdfReader.getPageSize(1));
readers.add(pdfReader);
totalPages += pdfReader.getNumberOfPages();
i++;
}
// Create a writer for the outputstream
PdfWriter writer = PdfWriter.getInstance(document, outputStream);
writer.setCompressionLevel(9);
document.open();
BaseFont bf = BaseFont.createFont(BaseFont.HELVETICA,
BaseFont.CP1252, BaseFont.NOT_EMBEDDED);
PdfContentByte cb = writer.getDirectContent(); // Holds the PDF data
PdfImportedPage page;
int currentPageNumber = 0;
int pageOfCurrentReaderPDF = 0;
Iterator<PdfReader> iteratorPDFReader = readers.iterator();
// Loop through the PDF files and add to the output.
while (iteratorPDFReader.hasNext()) {
PdfReader pdfReader = iteratorPDFReader.next();
// Create a new page in the target for each source page.
System.out.println("No. of pages "+pdfReader.getNumberOfPages());
i=0;
while (pageOfCurrentReaderPDF < pdfReader.getNumberOfPages()) {
Rectangle r=pdfReader.getPageSize(pdfReader.getPageN(pageOfCurrentReaderPDF+1));
if(r.getWidth()==792.0 && r.getHeight()==612.0)
document.setPageSize(PageSize.A4.rotate());
else
document.setPageSize(PageSize.A4);
document.newPage();
pageOfCurrentReaderPDF++;
currentPageNumber++;
i++;
page = writer.getImportedPage(pdfReader,
pageOfCurrentReaderPDF);
System.out.println("Width is "+page.getWidth());
System.out.println("Height is "+page.getHeight());
cb.newlineText();
cb.addTemplate(page, 0, 0);
// Code for pagination.
if (paginate) {
cb.beginText();
cb.setFontAndSize(bf, 9);
cb.showTextAligned(PdfContentByte.ALIGN_CENTER, ""
+ currentPageNumber + " of " + totalPages, 520,
5, 0);
cb.endText();
}
}
pageOfCurrentReaderPDF = 0;
}
outputStream.flush();
document.close();
outputStream.close();
System.out.println("Merging of Pdfs is done.......");
} catch (Exception e) {
e.printStackTrace();
} finally {
if (document.isOpen())
document.close();
try {
if (outputStream != null)
outputStream.close();
} catch (IOException ioe) {
ioe.printStackTrace();
}
}
}
}
Using the Document and PdfWriter class in combination with the addTemplate() method to merge documents is a bad idea. That's not what the addTemplate() method is meant for. You have explicitly or implicitly defined the page size for the Document you are working with. With the addTemplate() method, you add PdfImportedPage instances, and
when you add a new page with the same page size and rotation, you throw away all interactivity that exists in that page, but otherwise all is well,
when you add a new page with a different page size and rotation, you get the result you describe. Because of the difference in size, the imported page and the new page do not match. Parts get cut off, extra margins appear, rotations are different, etc.
This is all explained in chapter 6 of my book. You should use PdfCopy instead of PdfWriter. See for instance the FillFlattenMerge2 example:
Document document = new Document();
PdfCopy copy = new PdfSmartCopy(document, new FileOutputStream(dest));
document.open();
PdfReader reader;
String line = br.readLine();
// loop over readers
// add the PDF to PdfCopy
reader = new PdfReader(baos.toByteArray());
copy.addDocument(reader);
reader.close();
// end loop
document.close();
In your case, you also need to add page numbers, you can do this in a second go, as is done in the StampPageXofY example:
PdfReader reader = new PdfReader(src);
int n = reader.getNumberOfPages();
PdfStamper stamper = new PdfStamper(reader, new FileOutputStream(dest));
PdfContentByte pagecontent;
for (int i = 0; i < n; ) {
pagecontent = stamper.getOverContent(++i);
ColumnText.showTextAligned(pagecontent, Element.ALIGN_RIGHT,
new Phrase(String.format("page %s of %s", i, n)), 559, 806, 0);
}
stamper.close();
reader.close();
Or you can add them while merging, as is done in the MergeWithToc example.
Document document = new Document();
PdfCopy copy = new PdfCopy(document, new FileOutputStream(filename));
PageStamp stamp;
document.open();
int n;
int pageNo = 0;
PdfImportedPage page;
Chunk chunk;
for (Map.Entry<String, PdfReader> entry : filesToMerge.entrySet()) {
n = entry.getValue().getNumberOfPages();
for (int i = 0; i < n; ) {
pageNo++;
page = copy.getImportedPage(entry.getValue(), ++i);
stamp = copy.createPageStamp(page);
chunk = new Chunk(String.format("Page %d", pageNo));
if (i == 1)
chunk.setLocalDestination("p" + pageNo);
ColumnText.showTextAligned(stamp.getUnderContent(),
Element.ALIGN_RIGHT, new Phrase(chunk),
559, 810, 0);
stamp.alterContents();
copy.addPage(page);
}
}
document.close();
for (PdfReader r : filesToMerge.values()) {
r.close();
}
reader.close();
I strongly advise against using PdfWriter to merge documents! It's not impossible if you change the page size and the rotation of the page in the Document class, but you're making it harder on yourself. Moreover: using PdfWriter also throws away all interactivity (links, annotations,...) that exists in the pages you're merging. Your customer may experience that as a bug.
I am using iText library for merging individual pdfs. But the individual pdf always come on the bottom of the page. Any pointer how I can make it to display in the middle or on teh top. I have adjusted my code from http://viralpatel.net/blogs/itext-tutorial-merge-split-pdf-files-using-itext-jar/
public static void concatPDFs(OutputStream outputStream, boolean paginate) {
Document document = new Document();
try {
List<InputStream> pdfs = listPdf;
List<PdfReader> readers = new ArrayList<PdfReader>();
int totalPages = 0;
Iterator<InputStream> iteratorPDFs = pdfs.iterator();
// Create Readers for the pdfs.
while (iteratorPDFs.hasNext()) {
InputStream pdf = iteratorPDFs.next();
PdfReader pdfReader = new PdfReader(pdf);
readers.add(pdfReader);
totalPages += pdfReader.getNumberOfPages();
}
// Create a writer for the outputstream
PdfWriter writer = PdfWriter.getInstance(document, outputStream);
document.open();
BaseFont bf = BaseFont.createFont(BaseFont.HELVETICA,
BaseFont.CP1252, BaseFont.NOT_EMBEDDED);
PdfContentByte cb = writer.getDirectContent(); // Holds the PDF
// data
PdfImportedPage page;
int currentPageNumber = 0;
int pageOfCurrentReaderPDF = 0;
Iterator<PdfReader> iteratorPDFReader = readers.iterator();
// Loop through the PDF files and add to the output.
while (iteratorPDFReader.hasNext()) {
PdfReader pdfReader = iteratorPDFReader.next();
// Create a new page in the target for each source page.
while (pageOfCurrentReaderPDF < pdfReader.getNumberOfPages()) {
document.newPage();
pageOfCurrentReaderPDF++;
currentPageNumber++;
page = writer.getImportedPage(pdfReader,
pageOfCurrentReaderPDF);
cb.addTemplate(page, 0, 0);
// Code for pagination.
if (paginate) {
cb.beginText();
cb.setFontAndSize(bf, 9);
cb.showTextAligned(PdfContentByte.ALIGN_CENTER, ""
+ currentPageNumber + " of " + totalPages, 520,
5, 0);
cb.endText();
}
}
pageOfCurrentReaderPDF = 0;
}
outputStream.flush();
document.close();
outputStream.close();
} catch (Exception e) {
e.printStackTrace();
} finally {
if (document.isOpen())
document.close();
try {
if (outputStream != null)
outputStream.close();
} catch (IOException ioe) {
ioe.printStackTrace();
}
}
}
First to clear out about coordinate system. PDF coordinate system (0, 0) represents the bottom-left corner of the PDF page.
You can calculate new 'y' position for inserting page template like this:
y = new document heigh - imported page height
and then you can change your code to:
cb.addTemplate(page, 0, y);
The best you can do to merge PDF files is follow the intructions of the iText developer..
https://stackoverflow.com/a/24359217/2865036
Doing like he said, the format of your PDF files will not change
i am trying to merge 2 pdf in one. Merging is working fine but contents overflow from pdf page. A shown in attachment. Original Document pdf is as Follows.
After Merge Document is coming like this
Java code as follows :
BaseFont bf = BaseFont.createFont(BaseFont.TIMES_BOLD, BaseFont.CP1252, BaseFont.EMBEDDED);
//BaseFont bf= BaseFont.createFont();
PdfContentByte cb = writer.getDirectContent(); // Holds the PDF
// data
PdfImportedPage page;
int currentPageNumber = 0;
int pageOfCurrentReaderPDF = 0;
Iterator<PdfReader> iteratorPDFReader = readers.iterator();
// Loop through the PDF files and add to the output.
while (iteratorPDFReader.hasNext()) {
PdfReader pdfReader = iteratorPDFReader.next();
// Create a new page in the target for each source page.
while (pageOfCurrentReaderPDF < pdfReader.getNumberOfPages()) {
document.newPage();
pageOfCurrentReaderPDF++;
currentPageNumber++;
page = writer.getImportedPage(pdfReader,
pageOfCurrentReaderPDF);
cb.addTemplate(page, 0, 0);
// Code for pagination.
if (paginate) {
cb.beginText();
cb.setFontAndSize(bf, 9);
cb.showTextAligned(PdfContentByte.ALIGN_CENTER, ""
+ currentPageNumber + " of " + totalPages, 520,
5, 0);
cb.endText();
}
}
pageOfCurrentReaderPDF = 0;
}
please Help.
Please download chapter 6 of my book and take a look at table 6.1. You're making the mistake merging two documents using PdfWriter instead of using PdfCopy as documented. Take a look at listing 6.22 to find out how to add page numbers when using PdfCopy.
i used "PdfCopyFields" Snippet as follows :
public static boolean concatPDFFiles(List<String> listOfFiles,
String outputfilepath) throws FileNotFoundException, DocumentException {
PdfCopyFields copy = null;
try {
copy = new PdfCopyFields(new FileOutputStream(outputfilepath));
} catch (DocumentException ex) {
Logger.getLogger(MergerGoogleDocsToPDF.class.getName()).log(Level.SEVERE, null, ex);
}
try {
for (String fileName : listOfFiles) {
PdfReader reader1 = new PdfReader(fileName);
copy.addDocument(reader1);
}
} catch (IOException ex) {
Logger.getLogger(MergerGoogleDocsToPDF.class.getName()).log(Level.SEVERE, null, ex);
} finally {
copy.close();
}
if (new File(outputfilepath).exists()) {
double bytes = new File(outputfilepath).length();
//double kilobytes = (bytes / 1024);
if (bytes != 0) {
return true;
} else {
return false;
}
} else {
return false;
}
}