Merge PDF files with iText# and .NET
I’ve made a simple class to merge PDF files using iText#:
csharp:
using System;
using System.Collections.Generic;
using System.IO;
using iTextSharp.text;
using iTextSharp.text.pdf;
public class PdfMerge
{
private BaseFont baseFont;
private bool enablePagination = false;
private readonly List<PdfReader> documents;
private int totalPages;
public BaseFont BaseFont
{
get { return baseFont; }
set { baseFont = value; }
}
public bool EnablePagination
{
get { return enablePagination; }
set
{
enablePagination = value;
if (value && baseFont == null)
baseFont = BaseFont.CreateFont(BaseFont.HELVETICA, BaseFont.CP1252, BaseFont.NOT_EMBEDDED);
}
}
public List<PdfReader> Documents
{
get { return documents; }
}
public void AddDocument(string filename)
{
documents.Add(new PdfReader(filename));
}
public void AddDocument(Stream pdfStream)
{
documents.Add(new PdfReader(pdfStream));
}
public void AddDocument(byte[] pdfContents)
{
documents.Add(new PdfReader(pdfContents));
}
public void AddDocument(PdfReader pdfDocument)
{
documents.Add(pdfDocument);
}
public void Merge(string outputFilename)
{
Merge(new FileStream(outputFilename, FileMode.Create));
}
public void Merge(Stream outputStream)
{
if (outputStream == null || !outputStream.CanWrite)
throw new Exception("OutputStream es nulo o no se puede escribir en éste.");
Document newDocument = null;
try
{
newDocument = new Document();
PdfWriter pdfWriter = PdfWriter.GetInstance(newDocument, outputStream);
newDocument.Open();
PdfContentByte pdfContentByte = pdfWriter.DirectContent;
if (EnablePagination)
documents.ForEach(delegate(PdfReader doc)
{
totalPages += doc.NumberOfPages;
});
int currentPage = 1;
foreach (PdfReader pdfReader in documents)
{
for (int page = 1; page <= pdfReader.NumberOfPages; page++)
{
newDocument.NewPage();
PdfImportedPage importedPage = pdfWriter.GetImportedPage(pdfReader, page);
pdfContentByte.AddTemplate(importedPage, 0, 0);
if (EnablePagination)
{
pdfContentByte.BeginText();
pdfContentByte.SetFontAndSize(baseFont, 9);
pdfContentByte.ShowTextAligned(PdfContentByte.ALIGN_CENTER,
string.Format("{0} de {1}", currentPage++, totalPages), 520, 5, 0);
pdfContentByte.EndText();
}
}
}
}
finally
{
outputStream.Flush();
if (newDocument != null)
newDocument.Close();
outputStream.Close();
}
}
public PdfMerge()
{
documents = new List<PdfReader>();
}
}
using System.Collections.Generic;
using System.IO;
using iTextSharp.text;
using iTextSharp.text.pdf;
public class PdfMerge
{
private BaseFont baseFont;
private bool enablePagination = false;
private readonly List<PdfReader> documents;
private int totalPages;
public BaseFont BaseFont
{
get { return baseFont; }
set { baseFont = value; }
}
public bool EnablePagination
{
get { return enablePagination; }
set
{
enablePagination = value;
if (value && baseFont == null)
baseFont = BaseFont.CreateFont(BaseFont.HELVETICA, BaseFont.CP1252, BaseFont.NOT_EMBEDDED);
}
}
public List<PdfReader> Documents
{
get { return documents; }
}
public void AddDocument(string filename)
{
documents.Add(new PdfReader(filename));
}
public void AddDocument(Stream pdfStream)
{
documents.Add(new PdfReader(pdfStream));
}
public void AddDocument(byte[] pdfContents)
{
documents.Add(new PdfReader(pdfContents));
}
public void AddDocument(PdfReader pdfDocument)
{
documents.Add(pdfDocument);
}
public void Merge(string outputFilename)
{
Merge(new FileStream(outputFilename, FileMode.Create));
}
public void Merge(Stream outputStream)
{
if (outputStream == null || !outputStream.CanWrite)
throw new Exception("OutputStream es nulo o no se puede escribir en éste.");
Document newDocument = null;
try
{
newDocument = new Document();
PdfWriter pdfWriter = PdfWriter.GetInstance(newDocument, outputStream);
newDocument.Open();
PdfContentByte pdfContentByte = pdfWriter.DirectContent;
if (EnablePagination)
documents.ForEach(delegate(PdfReader doc)
{
totalPages += doc.NumberOfPages;
});
int currentPage = 1;
foreach (PdfReader pdfReader in documents)
{
for (int page = 1; page <= pdfReader.NumberOfPages; page++)
{
newDocument.NewPage();
PdfImportedPage importedPage = pdfWriter.GetImportedPage(pdfReader, page);
pdfContentByte.AddTemplate(importedPage, 0, 0);
if (EnablePagination)
{
pdfContentByte.BeginText();
pdfContentByte.SetFontAndSize(baseFont, 9);
pdfContentByte.ShowTextAligned(PdfContentByte.ALIGN_CENTER,
string.Format("{0} de {1}", currentPage++, totalPages), 520, 5, 0);
pdfContentByte.EndText();
}
}
}
}
finally
{
outputStream.Flush();
if (newDocument != null)
newDocument.Close();
outputStream.Close();
}
}
public PdfMerge()
{
documents = new List<PdfReader>();
}
}
Usage:
csharp:
string basePath = "c:\\pdf";
PdfMerge demo = new PdfMerge();
demo.AddDocument(Path.Combine(basePath, "static-dynamic-typing-meijer.pdf"));
demo.AddDocument(Path.Combine(basePath, "composable-memory-transactions.pdf"));
demo.Merge("mergedPapers.pdf");
Console.WriteLine("Archivo generado en: {0}", Path.GetFullPath("mergedPapers.pdf"));
PdfMerge demo = new PdfMerge();
demo.AddDocument(Path.Combine(basePath, "static-dynamic-typing-meijer.pdf"));
demo.AddDocument(Path.Combine(basePath, "composable-memory-transactions.pdf"));
demo.Merge("mergedPapers.pdf");
Console.WriteLine("Archivo generado en: {0}", Path.GetFullPath("mergedPapers.pdf"));
If you want the source code, you can download the Visual Studio 2005 solution.
Merge PDF files with iTextDotNet and .NET » Alex Concha 10:09 am on July 19, 2007 Enlace permanente
[...] the previous post I showed a class to merge PDF files using iText#, but it seems that there’s a better approach [...]
Luiz Estevam 2:27 pm on September 19, 2007 Enlace permanente
It forgives to invade its mail thus, but it would like to know if you has some source of iTextSharp that it makes convert of a page ASP/HTML for PDF directly. It forgives for the English but I am Brazilian. Thank very much.
Estevam
alex 7:49 am on September 20, 2007 Enlace permanente
Luiz, take a look to the following links:
http://www.ujihara.jp/iTextdotNET/en/examplesvb.html
http://geekswithblogs.net/casualjim/articles/59943.aspx
João Paulo 3:29 pm on March 24, 2008 Enlace permanente
Thank you for your piece of code, tt´s very useful.
daniela 3:06 pm on May 8, 2008 Enlace permanente
Olá Alex,
Eu já tinha feito um merge de PDF, mas mesmo assim testei o seu e tem o mesmo problema que o meu.
Toda vez que eu crio o novo documento eu perco todas as assinaturas digitais do original, você tem idéia como eu faço esse merge utilizando cópia de bytes?
Eu consegui fazer apenas uma cópia utilizando bytes sem perder as assinaturas digitais mas não consegui fazer o merge. Segue meu código.
PdfReader readersign = new PdfReader(pathpdfreader);
FileStream pdffile = new FileStream(pathpdfhashed, FileMode.Create );
PdfStamper stp = PdfStamper.CreateSignature(readersign, pdffile, \’\', null, true);
PdfSignatureAppearance sap = stp.SignatureAppearance;
PdfSignature dic = new PdfSignature(PdfName.ADOBE_PPKMS, PdfName.ADBE_PKCS7_SHA1);
sap.CryptoDictionary = dic;
int csize = 4000;
Hashtable exc = new Hashtable();
exc[PdfName.CONTENTS] = csize * 2 + 2;
sap.PreClose(exc);
byte[] outc = new byte[csize];
PdfDictionary dic2 = new PdfDictionary();
dic2.Put(PdfName.CONTENTS, new PdfString(outc).SetHexWriting(true));
sap.Close(dic2);
Mike L 12:38 am on July 1, 2008 Enlace permanente
I had to tweak my document object to take pagesize.letter in the constructor. I had to get my margins to line up the same way as my originals. Clearly, that could be more dynamic on my part to read the size of the incoming docs first.
However, my point is that this got me 99% of the way there. It was greatly helpful… thanks!
steve 8:57 am on July 21, 2008 Enlace permanente
Hi,
I want to ask you if this code with AddTemplate maked PDFs that are readable with not professional Acrobat Reader? I have heard that the normal Acrobat Reader is not supporting templates.
steve 9:02 am on July 21, 2008 Enlace permanente
Hi, again!
I\’m using your code and I\’m trying yo merge two equal pdf file s but it\’s not working because it says there are duplicate pages. What should I do if I want one and the same element (page) to repeat several times on a pdf document. Probably it\’s not doing implicit renaming of the form fields?
merge two PDF files in C# | keyongtech 12:01 pm on January 18, 2009 Enlace permanente
[...] files in C# Check out ITextSharp library. It\’s free and works with PDF documements. Sample: http://alex.buayacorp.com/merge-pdf-…t-and-net.html George "123456" <123456> wrote in message [...]
Martin 9:19 am on March 27, 2009 Enlace permanente
I am using your code, and i am trying merge two files, but it\’s not working, the sheet size is much larger. Not is letter or A4 !!! i add the next line in your code, document.SetPageSize(PageSize.A4), but not working !!!
duncan 8:11 am on June 1, 2009 Enlace permanente
hi,
i`m using this code it works but i had 2 files when i try to join them an exception will be thrown and says owner password i found in the internet to use the itext 2.0.2. Can someone tell me where i can download that dll please
thanks
Elijah S Holt 12:28 am on January 22, 2010 Enlace permanente
Thanks for the great code! I just have one little hiccup when I try to run it. I am merging two pdfs that are in landscape orientation. When I open the file that is the product of the merger, it opens in portrait mode. It can be viewed properly by clicking View -> Rotate View -> Clockwise but is there any way to have it written in landscape mode from the beginning?
Giuseppe 9:17 am on March 9, 2010 Enlace permanente
Hi, I’m working with a split function and I not your code doesn’t work with rotation. I suggest to insert this code:
if (rotation == 270)
{
pdfContentByte.AddTemplate(page, 0, 1f, -1f, 0, reader.GetPageSizeWithRotation(i).Width, 0);
}
else if (rotation == 90)
{
pdfContentByte.AddTemplate(page, 0, -1f, 1f, 0, 0, reader.GetPageSizeWithRotation(i).Height);
}
else if(rotation == 180)
{
pdfContentByte.AddTemplate(page, -1, 0, 0, -1f, reader.GetPageSizeWithRotation(i).Width, reader.GetPageSizeWithRotation(i).Height);
}
else
{
pdfContentByte.AddTemplate(page, 1f, 0, 0, 1f, 0, 0);
}
Thanks
Giuseppe
Sabrina 8:44 pm on March 13, 2010 Enlace permanente
Hi,
Thank you so much for the codes. Am truly grateful ! Works like magic!
Best regards
Gigiot 9:45 am on April 21, 2010 Enlace permanente
Hi, i’m using this code. I have 3 file .pdf and one of these have some TextField.
After the merge all TextField are disappear, why?
Richard 2:01 am on June 16, 2010 Enlace permanente
I’m using this code it works perfect, excellent. Thank You. Is simple to implement.