You have a couple of problems that I will try to get through you.
Firstly, the Document object is intended only for working with new PDF files, and not for modifying existing ones. Basically, the Document object is a bunch of wrapper classes that abstract away from the underlying parts of the PDF specification and allow you to work with higher-level things, such as paragraphs and reflowable content. These abstractions turn what you think of βparagraphsβ into raw commands that write a paragraph line one at a time without the relationship between the lines. When working with an existing document, there is no safe way to say how to melt the text so that these abstractions are not used.
Instead, you want to use the PdfStamper object. When working with this object, you have two options for working with potentially overlapping content, either your new text will be written on top of existing content, or the text will be written below. The two GetOverContent() or GetUnderContent() methods of the GetOverContent() object PdfStamper return a PdfContentByte object, which you can then write text with.
There are two main ways to write text manually or through a ColumnText object. If you made HTML, you can come up with a ColumnText object using a large fixed position, one row, one <TABLE> column. The advantage of ColumnText is that you can use higher-level abstractions like Paragraph .
Below is the full working C # 2010 WinForms application, targeting iTextSharp 5.1.2.0, which is shown above. See code comments for any questions. It should be pretty easy to convert to ASP.Net.
using System; using System.IO; using System.Windows.Forms; using iTextSharp.text; using iTextSharp.text.pdf; namespace WindowsFormsApplication1 { public partial class Form1 : Form { public Form1() { InitializeComponent(); } private void Form1_Load(object sender, EventArgs e) { string existingFile = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Desktop), "file1.pdf"); string newFile = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Desktop), "file2.pdf"); using (FileStream fs = new FileStream(existingFile, FileMode.Create, FileAccess.Write, FileShare.None)) { using (Document doc = new Document(PageSize.LETTER)) { using (PdfWriter writer = PdfWriter.GetInstance(doc, fs)) { doc.Open(); doc.Add(new Paragraph("This is a test")); doc.Close(); } } }
As for the second problem with FileStream vs MemoryStream , if you look at the method signature for almost every method (in fact, as far as I know) in iTextSharp, you will see that they all accept a Stream , not just a FileStream object. Every time you see this, even outside of iTextSharp, this means that you can pass any subclass of Stream that includes a MemoryStream object, everything else remains the same.
The code below is a slightly modified version above. I deleted most of the comments to make them shorter. The main change is that we use a MemoryStream instead of a FileStream . In addition, when we finish working with PDF, when you need to close the PdfStamper object before accessing the raw binary data. (The using status will do this for us automatically later, but also closes the stream, so we need to manually do it here.)
One more thing, never, never use the GetBuffer() method of a MemoryStream . This is similar to what you want (and I mistakenly used it too), but instead you want to use ToArray() . GetBuffer() contains uninitialized bytes, which usually create corrupted PDF files. In addition, instead of writing an HTTP response to the stream, I first store the bytes in an array. From a debugging point of view, this allows me to finish all the iTextSharp and System.IO code and make sure it is correct, and then do what I want with a raw byte array. In my case, I don't have a web server, so I write them to disk, but you can also just call Response.BinaryWrite(bytes)
string existingFile = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Desktop), "file1.pdf"); string newFile = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Desktop), "file2.pdf"); PdfReader reader = new PdfReader(existingFile); byte[] bytes; using(MemoryStream ms = new MemoryStream()){ using (PdfStamper stamper = new PdfStamper(reader, ms)) { PdfContentByte cb = stamper.GetOverContent(1); ColumnText ct = new ColumnText(cb); ct.SetSimpleColumn(100,100,500,200); ct.AddElement(new Paragraph("This was added using ColumnText")); ct.Go();