简体   繁体   中英

iTextSharp throws exception at closing document

I'm having problems with the following code in C# with Webforms in ASP.NET. I have spent quite a while looking for the answer, but no luck so far.

Document docPDF = new Document(PageSize.LETTER, this.LM, this.RM, this.TM, this.BM);
        this.writer = PdfWriter.GetInstance(docPDF, this.thePage.Response.OutputStream);

        docPDF.Open();

        for (int i = 0; i < elements.Count; i++)
        {
            docPDF.Add(elements[i]);
        }

        if (docPDF.IsOpen()) docPDF.Close();
        thePage.Response.HeaderEncoding = System.Text.Encoding.Default;
        thePage.Response.ContentType = "application/pdf; charset=utf-8";
        thePage.Response.AddHeader("content-disposition", "attachment;filename=" + fileName);
        thePage.Response.Cache.SetCacheability(HttpCacheability.NoCache);
        thePage.Response.Write(docPDF);
        thePage.Response.Flush();
        thePage.Response.End();

I'm getting a NullReferenceException at docPDF.Close();

All the variables that use the "this" keyword have been initialized, while debugging they do display values.

I'm using the exact same code in other projects, the same library (DLL) but this time it's simply not working. The elements array is a List< IElement> I fill with PdfPTable, Paragraph, Chunk and Image objects. When I debug it, they're there.

No error while opening the file I'm writing, no error when I add the elements, I check if the file is open and then try to close it, but then it simply won't close.

If I comment out the line, no exception is thrown, but the file is saved with errors and won't open to be read.

Any ideas?

UPDATE Here's the stack trace. As you can see, it's line 246, and following the stack trace, it does says that it is the Close() method. As a matter of fact, I added the "if (docPDF.IsOpen())" part after it started crashing. Debugging it, it does reach the docPDF.Close();

Line 244:        }
Line 245:        
Line 246:        if (docPDF.IsOpen()) docPDF.Close();
Line 247:        thePage.Response.HeaderEncoding = System.Text.Encoding.Default;
Line 248:        pagina.Response.ContentType = "application/pdf; charset=utf-8";

Source File: c:\Mao\Proyectos\Desarrollos\Avantare\PMTool\Codigo\App_Code\Comunicacion\Reportes\ExportadorPDF.cs    Line: 246 

Stack Trace: 


[NullReferenceException: Object reference not set to an instance of an object.]
   iTextSharp.text.pdf.CFFFontSubset.CreateNonCIDSubrs(Int32 Font, IndexBaseItem PrivateBase, OffsetItem Subrs) +135
   iTextSharp.text.pdf.CFFFontSubset.BuildNewFile(Int32 Font) +3389
   iTextSharp.text.pdf.CFFFontSubset.Process(String fontName) +275
   iTextSharp.text.pdf.TrueTypeFontUnicode.WriteFont(PdfWriter writer, PdfIndirectReference piref, Object[] parms) +1525
   iTextSharp.text.pdf.FontDetails.WriteFont(PdfWriter writer) +680
   iTextSharp.text.pdf.PdfWriter.AddSharedObjectsToBody() +244
   iTextSharp.text.pdf.PdfWriter.Close() +504
   iTextSharp.text.pdf.PdfDocument.Close() +291
   iTextSharp.text.Document.Close() +146
   ExportadorPDF.Exportar(String nombreArchivo) in c:\Mao\Proyectos\Desarrollos\Avantare\PMTool\Codigo\App_Code\Comunicacion\Reportes\ExportadorPDF.cs:246
   Reportes.Page_Load(Object sender, EventArgs e) in c:\Mao\Proyectos\Desarrollos\Avantare\PMTool\Codigo\Reportes.aspx.cs:32
   System.Web.Util.CalliHelper.EventArgFunctionCaller(IntPtr fp, Object o, Object t, EventArgs e) +14
   System.Web.Util.CalliEventHandlerDelegateProxy.Callback(Object sender, EventArgs e) +35
   System.Web.UI.Control.OnLoad(EventArgs e) +91
   System.Web.UI.Control.LoadRecursive() +74
   System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint) +2207

Another thing, perhaps this is worth mentioning to see any thoughts on the matter before I start changing the code, but as you can see in the stack, I'm calling the method that does this process from the Page_Load event. Could it be that the page hasn't fully loaded and I'm using its OutputStream? I'm not sure about it, because it doesn't crash on any line related to it, the PdfWriter line, for example.

UPDATE As suggested, I'm showing how I insert text, since it could be related to the font.

public void AddTextToParagraph(TextPDF text)
    {
        BaseFont baseFont = BaseFont.CreateFont(text.FontTypeName, BaseFont.IDENTITY_H, BaseFont.EMBEDDED);
        Font theFont = new Font(baseFont, text.Size, text.Style, new Color(text.FontColor));
        Chunk myContent = new Chunk(text.Text, theFont);
        this.theParagraph.Add(myContent);
    }

This I have in a class that has all the variables used, which are int and string (and the colour). After adding I debug theParagraph to see its content and everything is there.

The reference to the font is from the page with MapPath("~/Fonts/AlexanderSans.ttf"); ... Come to think of it, the font is something the end user purchased (yes, they paid for it), not Arial or any other standard font. But it is a TTF which I also use in Excel while exporting other files in the same application, so the file is not corrupted.

Anyway, this is starting to be anoying, isn't it? =)

Turns out mkl is right. Nothing to do with the stream nor the page. I simply changed the font oa standard Arial.ttf and work on the first try. The error never made a reference to anything at all but a null reference.

Why is the font a problem when you what to close the file, but not when you embed it to a text? Only the shadow knows. "If what's logical doesn't work, try the illogical", right?

Thanks to everyone, though.

Could you try this:

using (Document docPDF = new Document(PageSize.LETTER, this.LM, this.RM, this.TM, this.BM))
{
    this.writer = PdfWriter.GetInstance(docPDF, this.thePage.Response.OutputStream);

    docPDF.Open();

    for (int i = 0; i < elements.Count; i++)
    {
        docPDF.Add(elements[i]);
    }

    thePage.Response.HeaderEncoding = System.Text.Encoding.Default;
    thePage.Response.ContentType = "application/pdf; charset=utf-8";
    thePage.Response.AddHeader("content-disposition", "attachment;filename=" + fileName);
    thePage.Response.Cache.SetCacheability(HttpCacheability.NoCache);
    thePage.Response.Write(docPDF);
    thePage.Response.Flush();
    thePage.Response.End();
}

The using statement will call Dispose method of the Document. I checked the source code and the Dispose is implemented like this:

public virtual void Dispose() {
    if (IsOpen()) {
        Close();
    }
}

So it should close the document once it leaves the using block.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM