【问题标题】:iTextSharp throws exception at closing documentiTextSharp 在关闭文档时抛出异常
【发布时间】:2015-07-09 04:38:26
【问题描述】:

我在使用 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,我用 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,我也在 E​​xcel 中使用它,同时在同一个应用程序中导出其他文件,因此文件没有损坏。

不管怎样,这开始很烦人了,不是吗? =)

【问题讨论】:

  • 试试这个 if (docPDF.IsOpen()==true) docPDF.Close();
  • 发布的代码片段似乎正在工作,没有抛出 NullReference 异常。看看this answer 能不能解决你的问题?
  • 我得到一个 NullReferenceException - 你能提供那个异常的堆栈跟踪吗?
  • @mkl 我已经用堆栈跟踪和有关 Page_Load 事件的内容更新了问题。请检查一下。
  • 我强烈建议您不要直接写信给Response.OutputStream,而是写信给MemoryStream当PDF 完全完成后获取字节class="comcopy"> i> 然后写那些。您的代码是 100% 有效的,但 Response.OutputStream 由其他可能正在做您不期望的事情的“拥有”,而 MemoryStream 是“您的,只有您的”。一旦你完成了这种分离,你可能会发现将 NRE 隔离到真正的 iText 或真正的 ASP.Net 会更容易

标签: c# itextsharp nullreferenceexception


【解决方案1】:

事实证明 mkl 是对的。与流或页面无关。我只是将字体更改为标准 Arial.ttf 并进行第一次尝试。除了空引用之外,该错误从未引用任何内容。

为什么当你关闭文件时字体会出现问题,而当你将它嵌入到文本中时却没有?只有影子知道。 “如果合乎逻辑的东西行不通,试试不合逻辑的”,对吗?

谢谢大家。

【讨论】:

  • 为什么当你关闭文件时字体会出现问题,而不是当你将它嵌入到文本中时 - 实际嵌入发生在关闭文档时,因为只有然后就知道需要字体的哪些字形,并且只嵌入那些字形。
【解决方案2】:

你可以试试这个:

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

所以它应该在离开 using 块后关闭文档。

【讨论】:

  • 感谢您的建议。我会试试这个并将结果发回。
猜你喜欢
  • 2011-05-11
  • 1970-01-01
  • 2016-03-18
  • 2011-12-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-06-14
  • 1970-01-01
相关资源
最近更新 更多