Adding text to existing multipage PDF document in memorystream using iTextSharp
c#, c#-4.0, itext, pdf, stream
Solution
The code below shows off a full-working example of creating a PDF in memory and then performing a second pass, also in memory. It does what @mkl says and closes all iText parts before trying to grab the raw bytes from the stream. It also uses `GetOverContent()` to draw "on top" of the previous pdf. See the code comments for more details.
//Bytes will hold our final PDFs
byte[] bytes;
//Create an in-memory PDF
using (var ms = new MemoryStream()) {
using (var doc = new Document()) {
using (var writer = PdfWriter.GetInstance(doc, ms)) {
doc.Open();
//Create a bunch of pages and add text, nothing special here
for (var i = 1; i <= 10; i++) {
doc.NewPage();
doc.Add(new Paragraph(String.Format("First Pass - Page {0}", i)));
}
doc.Close();
}
}
//Right before disposing of the MemoryStream grab all of the bytes
bytes = ms.ToArray();
}
//Another in-memory PDF
using (var ms = new MemoryStream()) {
//Bind a reader to the bytes that we created above
using (var reader = new PdfReader(bytes)) {
//Store our page count
var pageCount = reader.NumberOfPages;
//Bind a stamper to our reader
using (var stamper = new PdfStamper(reader, ms)) {
//Setup a font to use
var baseFont = BaseFont.CreateFont(BaseFont.HELVETICA_BOLD, BaseFont.CP1252, BaseFont.NOT_EMBEDDED);
//Loop through each page
for (var i = 1; i <= pageCount; i++) {
//Get the raw PDF stream "on top" of the existing content
var cb = stamper.GetOverContent(i);
//Draw some text
cb.BeginText();
cb.SetFontAndSize(baseFont, 18);
cb.ShowText(String.Format("Second Pass - Page {0}", i));
cb.EndText();
}
}
}
//Once again, grab the bytes before closing things out
bytes = ms.ToArray();
}
//Just to see the final results I'm writing these bytes to disk but you could do whatever
var testFile = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Desktop), "test.pdf");
System.IO.File.WriteAllBytes(testFile, bytes);
Problem
I am trying to add text to an existing PDF file using iTextSharp. I have been reading many posts, including the popular thread here. I have some differences: - My PDF are X pages long - I want to keep everything in memory, and never have a file stored on my filesystem So I tried to modify the code, so it takes in a byte array and returns a byte array. I have come this far: - The code compiles and runs - My out byte array has a different length than my in byte array My problem: - I cannot see my added text when i later store the modified byte array and open it in my PDF reader I don't get why. From every StackOverflow post I have seen, I do the same. using the `DirectContent`, I use `BeginText` and write a text. However, i cannot see it, no matter how I move the position around. Any idea what is missing from my code? ``` public static byte[] WriteIdOnPdf(byte[] inPDF, string str) { byte[] finalBytes; // open the reader using (PdfReader reader = new PdfReader(inPDF)) { Rectangle size = reader.GetPageSizeWithRotation(1); using (Document document = new Document(size)) { // open the writer using (MemoryStream ms = new MemoryStream()) { using (PdfWriter writer = PdfWriter.GetInstance(document, ms)) { document.Open(); for (var i = 1; i <= reader.NumberOfPages; i++) { document.NewPage(); var baseFont = BaseFont.CreateFont(BaseFont.HELVETICA_BOLD, BaseFont.CP1252, BaseFont.NOT_EMBEDDED); var importedPage = writer.GetImportedPage(reader, i); var contentByte = writer.DirectContent; contentByte.BeginText(); contentByte.SetFontAndSize(baseFont, 18); var multiLineString = "Hello,\r\nWorld!"; contentByte.ShowTextAligned(PdfContentByte.ALIGN_LEFT, multiLineString,100, 200, 0); contentByte.EndText(); contentByte.AddTemplate(importedPage, 0, 0); } document.Close(); ms.Close(); writer.Close(); reader.Close(); } finalBytes = ms.ToArray(); } } } return finalBytes; } ```