关闭文档

时间:2015-07-09 04:38:26

标签: c# itextsharp nullreferenceexception

我在ASP.NET中使用Webforms的C#中遇到以下代码问题。我花了很长时间寻找答案,但到目前为止没有运气。

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();

我在docPDF.Close();

获得了NullReferenceException

所有使用“this”关键字的变量都已初始化,而调试则显示值。

我在其他项目中使用完全相同的代码,相同的库(DLL),但这次它根本不起作用。元素数组是List&lt; IElement&GT;我填写了PdfPTable,Paragraph,Chunk和Image对象。当我调试它时,它们就在那里。

打开我正在编写的文件时没有错误,添加元素时没有错误,我检查文件是否打开然后尝试关闭它,但之后它根本就不会关闭。

如果我注释掉该行,则不会抛出任何异常,但该文件将保存并显示错误,并且无法打开以进行读取。

有什么想法吗?

更新 这是堆栈跟踪。如您所见,它是第246行,并且在堆栈跟踪之后,它确实说它是Close()方法。事实上,我在开始崩溃后添加了“if(docPDF.IsOpen())”部分。调试它,它确实到达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

另一件事,也许值得一提的是在我开始更改代码之前看到有关此问题的任何想法,但正如您在堆栈中看到的那样,我正在调用从Page_Load事件执行此过程的方法。可能是页面没有完全加载,我正在使用它的OutputStream?我不确定它,因为它不会在与它相关的任何行上崩溃,例如PdfWriter行。

更新 正如所建议的,我正在展示如何插入文本,因为它可能与字体有关。

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);
    }

我在一个包含所有变量的类中,它们是int和string(以及颜色)。添加后我调试theParagraph以查看其内容,一切都在那里。

对字体的引用来自带有MapPath的页面(“〜/ Fonts / AlexanderSans.ttf”); ...想想看,字体是最终用户购买的东西(是的,他们付钱),而不是Arial或任何其他标准字体。但它是一个TTF,我也在Excel中使用同时在同一个应用程序中导出其他文件,因此文件没有损坏。

无论如何,这开始变得很烦人,不是吗? =)

2 个答案:

答案 0 :(得分:1)

原来mkl是对的。与流和页面无关。我只是改变了标准Arial.ttf的字体并在第一次尝试时工作。除了空引用之外,该错误从未引用任何内容。

当您关闭文件时,为什么字体会出现问题,而在将文本嵌入文本时则不然?只有影子知道。 “如果什么是合乎逻辑的不起作用,试试不合逻辑的”,对吗?

感谢所有人。

答案 1 :(得分:0)

你可以试试这个:

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();
}

using语句将调用Document的Dispose方法。我检查了源代码,Dispose实现如下:

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

因此,一旦文档离开使用块,它应该关闭文档。