The main issue in your code is that you assume that the PdfWriter
descendant iText_Stamper.Writer
can be used like a Document
to which you can add text chunks using the Add
method, and expect iTextSharp to layout such material automatically.
The class hierarchy unfortunately suggests this as both PdfWriter
and Document
implement the interface IElementListener
which provides a method bool Add(IElement element)
.
Nonetheless, this assumption is wrong, the class hierarchies overlap for internal code reuse reasons, not to suggest similar usages; the Add
implementation of the PdfWriter
descendant iText_Stamper.Writer
merely returns false
and does not even attempt to add the given element to the document.
In particular in case of pages the stamper retrieved from the underlying PdfReader
(and didn't add to them) this does make sense: If there is content somehow scattered across a page, where should the stamper add the new content? Should it consider the existing content background material and start at the top? Or should it somehow find a big unused page area and paint the elements there? (In case of newly added pages, though, the stamper indeed could have been programmed to serve like a regular PdfWriter
and have allowed linkage with a Document
to automatically layout content...)
Thus, to allow for new content to be automatically layout'ed, you have to tell iTextSharp where to put the content. You can do this by means of a ColumnText
instance like this:
using (PdfReader reader = new PdfReader(source))
using (PdfStamper stamper = new PdfStamper(reader, new FileStream(result, FileMode.Create, FileAccess.Write)))
{
PdfFileSpecification pfs = PdfFileSpecification.FileEmbedded(stamper.Writer, pdfPath, pdfName, pdfBytes);
pfs.AddDescription(pdfDesc, true);
stamper.AddFileAttachment(pdfDesc, pfs);
PdfContentByte cb = stamper.GetOverContent(1);
ColumnText ct = new ColumnText(cb);
ct.SetSimpleColumn(30, 30, reader.GetPageSize(1).GetRight(30), 60);
PdfTargetDictionary target = new PdfTargetDictionary(true);
target.EmbeddedFileName = pdfDesc;
PdfDestination dest = new PdfDestination(PdfDestination.FIT);
dest.AddFirst(new PdfNumber(1));
PdfAction action = PdfAction.GotoEmbedded(null, target, dest, true);
Chunk chunk = new Chunk(pdfDesc);
chunk.SetAction(action);
ct.AddElement(chunk);
ct.Go();
}
(I used somewhat more descriptive names than your f.sDataFileName, s, b
)
In the course of layout'ing your chunks, ColumnText
also establishes the desired goto-emebedded links.
By the way, from your writing embedded files and using a PdfAction.GotoEmbedded
I assumed you attach another PDF. If that assumption happens to be wrong, you might want to use PdfAnnotation.CreateFileAttachment
instead