5

我在 Windows 窗体程序中遇到了来自 iTextSharp 的 HTMLWorker.Parse 的问题。每次我执行代码并以 HTMLWorker.Parse 开头时,它都会给出 objectDisposedException。异常表示它无法访问已关闭的文件。但是我检查了很多次,都找不到关闭的文件。这是代码:

class HtmlToPdfConverter
 {
             private iTextSharp.text.Document doc = new iTextSharp.text.Document();

     public HtmlToPdfConverter()
     {
        this.doc.SetPageSize(PageSize.A4);

     }

     public string Run(string html, string pdfName)
     {
        try
        {
            using (doc)
            {
                StyleSheet styles = new StyleSheet();
                using (PdfWriter writer = PdfWriter.GetInstance(this.doc, new     FileStream(@"Z:\programs\" + pdfName + ".pdf", FileMode.Create)))
                {
                    this.doc.Open();
                    this.doc.OpenDocument();
                    this.doc.NewPage();
                    if (this.doc.IsOpen() == true)
                    {
                        StringReader reader = new StringReader(html);
                        //XMLWorkerHelper.GetInstance().ParseXHtml(writer, doc, reader);
                        this.doc.Add(new Paragraph(" "));
                        HTMLWorker worker = new HTMLWorker(this.doc);
                        worker.Open();
                        worker.StartDocument();
                        worker.NewPage();
                        worker.Parse(reader);
                        worker.SetStyleSheet(styles);

                        List<IElement> ie = iTextSharp.text.html.simpleparser.HTMLWorker.ParseToList(reader, null);

                        foreach (IElement element in ie)
                        {
                            this.doc.Add((IElement)element);
                        }

                        worker.EndDocument();
                        worker.Close();
                    }
                }
            }
            return string.Empty;
        }
        catch (Exception ex)
        {
            return ex.Message;
        }

    }
 }

这是一个例外:

System.ObjectDisposedException was caught
  Message=Cannot access a closed file.
  Source=mscorlib
  ObjectName=""
  StackTrace:
       at System.IO.__Error.FileNotOpen()
       at System.IO.FileStream.Write(Byte[] array, Int32 offset, Int32 count)
       at iTextSharp.text.pdf.OutputStreamCounter.Write(Byte[] buffer, Int32 offset, Int32 count)
       at iTextSharp.text.pdf.PdfIndirectObject.WriteTo(Stream os)
       at iTextSharp.text.pdf.PdfWriter.PdfBody.Add(PdfObject objecta, Int32 refNumber, Boolean inObjStm)
       at iTextSharp.text.pdf.PdfWriter.PdfBody.Add(PdfObject objecta, Int32 refNumber)
       at iTextSharp.text.pdf.PdfWriter.PdfBody.Add(PdfObject objecta, PdfIndirectReference refa)
       at iTextSharp.text.pdf.PdfWriter.AddToBody(PdfObject objecta, PdfIndirectReference refa)
       at iTextSharp.text.pdf.Type1Font.WriteFont(PdfWriter writer, PdfIndirectReference piref, Object[] parms)
       at iTextSharp.text.pdf.FontDetails.WriteFont(PdfWriter writer)
       at iTextSharp.text.pdf.PdfWriter.AddSharedObjectsToBody()
       at iTextSharp.text.pdf.PdfWriter.Close()
       at iTextSharp.text.DocWriter.Dispose()
       at WebPageExtraction.HtmlToPdfConverter.Run(String html, String pdfName)
  InnerException: 
4

1 回答 1

5

您正在尝试在它已经处理后调用 close 方法。

您有一个using自动处理对象的块,因此只需删除这两行:

doc.CloseDocument();
doc.Close();

如果您不相信内部处置代码可以正确关闭文档并且无论如何都想自己执行此操作,请在using块内执行此操作:

using (doc)
{
    StyleSheet styles = new StyleSheet();
    using (PdfWriter writer = PdfWriter.GetInstance(this.doc, new     FileStream(@"Z:\programs\" + pdfName + ".pdf", FileMode.Create)))
    {
        //.....
    }
    doc.CloseDocument();
    doc.Close();
}

编辑:在自己尝试了您的代码后,我发现了更多问题,并找到了您遇到错误的真正原因:

  • 您正在关闭和处置全局对象doc,并且永远不会创建新实例。
  • 您不会处理所有对象,这可能会导致内存泄漏或锁定文件。
  • 您收到的错误是因为默认情况下,PdfWriter 正在关闭它正在使用的 Stream,并且在处理时,作者正在尝试使用此流。所以要解决这个问题,你必须自己关闭流并告诉作者不要这样做。

完整的固定代码:

Document doc = new Document();
StyleSheet styles = new StyleSheet();
string filePath = @"Z:\programs\" + pdfName + ".pdf";
using (FileStream pdfStream = new FileStream(filePath, FileMode.Create))
{
    using (PdfWriter writer = PdfWriter.GetInstance(doc, pdfStream))
    {
        writer.CloseStream = false;
        doc.Open();
        doc.OpenDocument();
        doc.NewPage();
        if (doc.IsOpen() == true)
        {
            using (StringReader reader = new StringReader(html))
            {
                //XMLWorkerHelper.GetInstance().ParseXHtml(writer, doc, reader);
                doc.Add(new Paragraph(" "));
                using (HTMLWorker worker = new HTMLWorker(doc))
                {
                    worker.Open();
                    worker.StartDocument();
                    worker.NewPage();
                    worker.Parse(reader);
                    worker.SetStyleSheet(styles);
                    List<IElement> ie = iTextSharp.text.html.simpleparser.HTMLWorker.ParseToList(reader, null);
                    foreach (IElement element in ie)
                    {
                        doc.Add((IElement)element);
                    }
                    worker.EndDocument();
                    worker.Close();
                }
            }
        }
        writer.Close();
    }
}

doc.CloseDocument();
doc.Close();
doc.Dispose(); 
于 2012-09-03T10:21:34.953 回答