Search code examples
c#pdfitextidisposablepdfstamper

PdfStamper being disposed


The PdfStamper I'm passing in to this method is being disposed of at the end of the method - why, and how do I stop it? I'm trying to create a page object from the template, which I can then add to the PdfStamper X number of times.

//real code
public void DoSpecialAction(PdfStamper pdfStamper)
{
    using (var pdfTemplate = new PdfReader(_extraPageTemplatePath))
    using (var pdfReader = new PdfReader(pdfTemplate))
    {
        PdfImportedPage page = pdfStamper.GetImportedPage(pdfReader, 1);
        pdfStamper.InsertPage(3, pdfReader.GetPageSize(1));
        PdfContentByte pb = pdfStamper.GetUnderContent(3);
        pb.AddTemplate(page, 0, 0);
    }
}

the program structure is as follows:

//psuedocode
class PrintFieldsToPdf {
    foreach (normalfield) {
        PrintNormalFields();
    }

    foreach (specialaction) {
        DoSpecialAction(pdfStamper);
    }

    pdfStamper.Close(); //at this point the object has been deallocated
}

Throwing the following exception:

An exception of type 'System.ObjectDisposedException' occurred in mscorlib.dll but was not handled in user code

Additional information: Cannot access a closed file.

Solution

  • The OP eventually commented:

    I have a hunch it may be that the page object never actually gets copied until the PdfStamper calls Close and writes the file, and therefore the PdfReader I'm using to read the extra page template is causing the issue, as it is disposed of at the end of my method, before PdfStamper is closed.

    His hunch was correct: The copying of at least certain parts of the original page is delayed until the PdfStamper is being closed. This allows for certain optimizations in case multiple pages from the same PdfReader instance are imported in separate calls.

    The use case of imports from many different PdfReaders had also been on the mind of the iText(Sharp) developers. So they provided a way to tell the PdfStamper to copy everything required from a given PdfReader at the time the user is sure he won't copy anything else from it:

    public void DoSpecialAction(PdfStamper pdfStamper)
    {
        using (var pdfTemplate = new PdfReader(_extraPageTemplatePath))
        using (var pdfReader = new PdfReader(pdfTemplate))
        {
            PdfImportedPage page = pdfStamper.GetImportedPage(pdfReader, 1);
            pdfStamper.InsertPage(3, pdfReader.GetPageSize(1));
            PdfContentByte pb = pdfStamper.GetUnderContent(3);
            pb.AddTemplate(page, 0, 0);
            // Copy everything required from the PdfReader
            pdfStamper.Writer.FreeReader(pdfReader);
        }
    }