Introduction
There are a couple of PDF mergers available on the Internet. But, either they are commercial products or don't support printing of the header and/or footer text, which is particularly interesting, e.g., to print the page number.
Background
The presented PDF merger uses the open source PDF library iTextSharp to process PDF files. The sample solution also includes a tiny Windows Forms application to demonstrate the functionality.
Using the code
For the merge process, the PDF library takes advantage of the PDF page events of the iTextSharp.text.pdf.PdfWriter object. During the initialization of the PdfPageEvent instance (which inherits from iTextSharp.text.pdf.IPdfPageEvent), necessary information for the header/footer text could be passed in to the constructor call:
writer.PageEvent = new PdfPageEvents();
It is important that the header and the footer text, both, are rendered in the 'public void OnEndPage(PdfWriter writer, Document document)' method. The 'public void OnStartPage(PdfWriter writer, Document document)' is not accurate.
Even though the shown sample is very basic, it generally gives a good overview of how the header and the footer can be populated, e.g., with picture(s), text(s)...
The source code
using System;
using System.Collections.Generic;
using System.IO;
using iTextSharp.text;
using iTextSharp.text.pdf;
namespace SmartSoft.PdfLibrary
{
public static class PdfMerger
{
public static byte[] MergeFiles(List<byte[]> sourceFiles)
{
Document document = new Document();
MemoryStream output = new MemoryStream();
try
{
PdfWriter writer = PdfWriter.GetInstance(document, output);
writer.PageEvent = new PdfPageEvents();
document.Open();
PdfContentByte content = writer.DirectContent;
for (int fileCounter = 0; fileCounter < sourceFiles.Count; fileCounter++)
{
PdfReader reader = new PdfReader(sourceFiles[fileCounter]);
int numberOfPages = reader.NumberOfPages;
for (int currentPageIndex = 1; currentPageIndex <=
numberOfPages; currentPageIndex++)
{
document.SetPageSize(
reader.GetPageSizeWithRotation(currentPageIndex));
document.NewPage();
PdfImportedPage importedPage =
writer.GetImportedPage(reader, currentPageIndex);
int pageOrientation = reader.GetPageRotation(currentPageIndex);
if ((pageOrientation == 90) || (pageOrientation == 270))
{
content.AddTemplate(importedPage, 0, -1f, 1f, 0, 0,
reader.GetPageSizeWithRotation(currentPageIndex).Height);
}
else
{
content.AddTemplate(importedPage, 1f, 0, 0, 1f, 0, 0);
}
}
}
}
catch (Exception exception)
{
throw new Exception("There has an unexpected exception" +
" occured during the pdf merging process.", exception);
}
finally
{
document.Close();
}
return output.GetBuffer();
}
}
internal class PdfPageEvents : IPdfPageEvent
{
#region members
private BaseFont _baseFont = null;
private PdfContentByte _content;
#endregion
#region IPdfPageEvent Members
public void OnOpenDocument(PdfWriter writer, Document document)
{
_baseFont = BaseFont.CreateFont(BaseFont.HELVETICA,
BaseFont.CP1252, BaseFont.NOT_EMBEDDED);
_content = writer.DirectContent;
}
public void OnStartPage(PdfWriter writer, Document document)
{}
public void OnEndPage(PdfWriter writer, Document document)
{
string headerText = "PDF Merger by Smart-Soft";
_content.BeginText();
_content.SetFontAndSize(_baseFont, 8);
_content.SetTextMatrix(GetCenterTextPosition(headerText,
writer), writer.PageSize.Height - 10);
_content.ShowText(headerText);
_content.EndText();
string text = "Page " + writer.PageNumber;
_content.BeginText();
_content.SetFontAndSize(_baseFont, 8);
_content.SetTextMatrix(GetCenterTextPosition(text, writer), 10);
_content.ShowText(text);
_content.EndText();
}
public void OnCloseDocument(PdfWriter writer, Document document)
{}
public void OnParagraph(PdfWriter writer,
Document document, float paragraphPosition)
{}
public void OnParagraphEnd(PdfWriter writer,
Document document, float paragraphPosition)
{}
public void OnChapter(PdfWriter writer, Document document,
float paragraphPosition, Paragraph title)
{}
public void OnChapterEnd(PdfWriter writer,
Document document, float paragraphPosition)
{}
public void OnSection(PdfWriter writer, Document document,
float paragraphPosition, int depth, Paragraph title)
{}
public void OnSectionEnd(PdfWriter writer,
Document document, float paragraphPosition)
{}
public void OnGenericTag(PdfWriter writer, Document document,
Rectangle rect, string text)
{}
#endregion
private float GetCenterTextPosition(string text, PdfWriter writer)
{
return writer.PageSize.Width / 2 - _baseFont.GetWidthPoint(text, 8) / 2;
}
}
}
History
- 01.08.2008 - Article created.