元素不允许错误itextSharp

时间:2017-01-31 11:03:27

标签: c# pdf itext

iam尝试使用itextsharp将html转换为pdf。但总是得到错误'元素不被允许'使用HtmlAgilityPack格式化的Html。 .................................................. .................................................. .................................................. ...............................................  这是我的代码

 hDocument.LoadHtml(html);
            var closedTags = hDocument.DocumentNode.WriteTo();
            var _cssSource = Server.MapPath("~/css/style.css");
            var css = System.IO.File.ReadAllText(_cssSource);
            var memoryStram = new MemoryStream();
            var memmoryStram = new MemoryStream();
            var document = new Document(PageSize.A4, 10, 10, 10, 10);
            var writer = PdfWriter.GetInstance(document, memmoryStram);
            document.Open();
            using (var cssMemoryStream = new MemoryStream(System.Text.Encoding.UTF8.GetBytes(css)))
            {
                using (var htmlMemoryStream = new MemoryStream(System.Text.Encoding.UTF8.GetBytes(closedTags)))
                {
                    // XMLWorker _worker = new XMLWorker(
                    StringReader htmls = new StringReader(html);
                    var p = XMLWorkerHelper.GetInstance();
                    p.ParseXHtml(writer, document, htmlMemoryStream, cssMemoryStream);
                }
            }
            document.Close();

错误:

         at iTextSharp.text.pdf.ColumnText.AddElement(IElement element)
      at iTextSharp.text.pdf.PdfPCell.AddElement(IElement element)
     at iTextSharp.tool.xml.html.table.TableData.End(IWorkerContext ctx, Tag tag, IList`1 currentContent)
   at iTextSharp.tool.xml.html.AbstractTagProcessor.EndElement(IWorkerContext ctx, Tag tag, IList`1 currentContent)
   at iTextSharp.tool.xml.pipeline.html.HtmlPipeline.Close(IWorkerContext context, Tag t, ProcessObject po)
 at iTextSharp.tool.xml.XMLWorker.EndElement(String tag, String ns)
 at iTextSharp.tool.xml.parser.XMLParser.EndElement()
 at iTextSharp.tool.xml.parser.state.ClosingTagState.Process(Char character)
 at iTextSharp.tool.xml.parser.XMLParser.ParseWithReader(TextReader reader)
  at iTextSharp.tool.xml.parser.XMLParser.Parse(TextReader reader)
 at iTextSharp.tool.xml.parser.XMLParser.Parse(Stream inp)
  at iTextSharp.tool.xml.XMLWorkerHelper.ParseXHtml(PdfWriter writer, Document doc, Stream inp, Stream inCssFile, Encoding charset, IFontProvider fontProvider, String resourcesRootPath)
  at iTextSharp.tool.xml.XMLWorkerHelper.ParseXHtml(PdfWriter writer, Document doc, Stream inp, Stream inCssFile, Encoding charset, IFontProvider fontProvider)
  at iTextSharp.tool.xml.XMLWorkerHelper.ParseXHtml(PdfWriter writer, Document doc, Stream inp, Stream inCssFile)
  at IBATechnologies.IBA.SyncApp.Interface.Controllers.UtilitiesController.pdfBytes(String html) in E:\IBASyncApp\IBA.SyncApp.Interface\IBATechnologies.IBA.SyncApp.Interface\Controllers\UtilitiesController.cs:line 54

closedTags

     <!-- ngInclude: _rpt.tmpUrl --><div class="col-all-12 PDF-report-holder   ng-  scope" ng-include="_rpt.tmpUrl"><table id="myTable" class="table-responsive ng-scope">
     <tbody><tr class="header">
   <th colspan="5">
   <h2 class="col-all-12"> Branch</h2>
   <p class="col-all-12 ng-binding">WMS Stock Status - Item Summary</p>
  </th>

 <th class="-Pdf-logo">
       <a href="http://technologies.com/" class="col-all-12"><img       src="/image/default/logo.png" /></a>
     </th>
     </tr>
     <tr class="-Pdf-head">
  <td>SKU</td>
   <td>Base Unit</td>
   <td>Base Qty</td>
  <td>Pltpos(s)</td>
   <td>CBM</td>
   <td>Weight TON</td>

    </tr>
     </tbody><!-- ngRepeat: cust in _rpt.data --><tbody ng-repeat="cust in _rpt.data"    class="ng-scope">
<tr>
<td colspan="6"><strong><p class="ng-binding">Test Customer</p></strong></td>

 </tr>
  <!-- ngRepeat: row in cust.itemGroup --><tr ng-repeat="row in    cust.itemGroup"     ng-repeat-finished="rpt_ng_repeat" class="ng-scope">
     <td><p class="ng-binding">100 Test Item</p></td>
      <td><p class="ng-binding">PLT</p></td>
      <td><p class="ng-binding">68</p></td>
        <td><p class="ng-binding">68</p></td>
       <td><p class="ng-binding">68</p></td>
       <td><p class="ng-binding">0.068</p></td>
       </tr><!-- end ngRepeat: row in cust.itemGroup -->
       <tr class="-Pdf-head">
       <td colspan="3"><p>Total</p></td>
     <td><p class="ng-binding">68</p></td>
   <td><p class="ng-binding">68</p></td>
   <td><p class="ng-binding">0.068</p></td>
   </tr>
       </tbody><!-- end ngRepeat: cust in _rpt.data -->
      </table>
    </div>

api致电

  public ActionResult DownloadPdf(string file_name,string html)
    {

        var _memStream = pdfBytes(html);
        var _pdfDoc = new PdfContent
        {
            MemoryStream = _memStream,
            FileName = file_name
        };
        return _pdfDoc;
    }

回复

public class PdfContent : ActionResult
{
    public MemoryStream MemoryStream { get; set; }
    public string FileName { get; set; }
    public override void ExecuteResult(ControllerContext context)
    {
        if (context == null)
        {
            throw new ArgumentNullException("context");
        }
        var response = context.HttpContext.Response;
        response.ContentType = "pdf/application";
        response.AddHeader("content-disposition", "attachment;filename=" + FileName + ".pdf");
        response.OutputStream.Write(MemoryStream.GetBuffer(), 0, MemoryStream.GetBuffer().Length);
    }
}

CSS

.PDF-report{position:fixed; top:0; right:-100%; background:#fff; width:75%; height:100%; z-index:100; padding:10px; border-left:1px solid #ccc} .PDF - report - active{ right: 0}
                        .PDF - report table{background:#fff; min-width:100%}.PDF - report table td{ min - width:100px;}.IBA - Pdf - logo img{ float:right}.IBA - Pdf - head{ border - top:5px solid #000; font-weight:bold }.PDF - report - holder{ height: 100 %; overflow: scroll} .col-all-12{width:100%;}
                        .col-all-12, .all-col{height:auto; padding:0; margin:0; float:left}

1 个答案:

答案 0 :(得分:5)

原因

显然,iText XMLWorker不接受标题元素(h1h2h3h4h5或{{1在表头元素(h6)内:如果你在这里删除了th元素

h2

或制作它,例如一个段落元素(<th colspan="5"> <h2 class="col-all-12"> Branch</h2> <p class="col-all-12 ng-binding">WMS Stock Status - Item Summary</p> </th> ),不再有例外。

您可以使用缩减示例验证这一点:

p

<table><tr><td><h1>Test</h1></td></tr></table>

两者都由<table><tr><th><p>Test</p></th></tr></table> 处理,但

XMLWorker

被拒绝,但与HTML相同。

规范

根据HTML5规范标题,表头文件中的元素实际上是不允许的:

  

4.9.10 <table><tr><th><h1>Test</h1></th></tr></table> 元素

     

[...]

     

内容模型:

     

流内容,但没有页眉,页脚,切片内容或标题内容后代。

HTML5 section 4.9 Tabular Data

其中标题内容定义为

  

3.2.4.1.4标题内容

     

标题内容定义了标题的标题(无论是使用切片内容元素明确标记,还是标题内容本身隐含的标记)。

     

=&GT; h1 h2 h3 h4 h5 h6

HTML5 section 3 Semantics, structure, and APIs of HTML documents

底线

因此,您的HTML输入无效HTML,因此,iText(或任何HTML处理器)可能无法处理它。

测试代码

作为参考,从您的代码派生,这是我用于测试的代码:

th

html和css中的额外空格都已从源中删除,因为我认为它们是复制到堆栈溢出时引入的工件。如果这个假设是错误的,原始的HTML和CSS应该在继续之前进行清理。

此外,删除了未使用的代码,例如public void CreatePdfAjithOriginal() { String html = "<!-- ngInclude: _rpt.tmpUrl -->" + "<div class=\"col-all-12 PDF-report-holder ng-scope\" ng-include=\"_rpt.tmpUrl\">" + "<table id=\"myTable\" class=\"table-responsive ng-scope\">" + "<tbody>" + "<tr class=\"header\">" + "<th colspan=\"5\">" // + "<h2 class=\"col-all-12\"> Branch</h2>" + "<p class=\"col-all-12 ng-binding\">WMS Stock Status - Item Summary</p>" + "</th>" + "<th class=\"-Pdf-logo\">" + "<a href=\"http://technologies.com/\" class=\"col-all-12\"><img src=\"/image/default/logo.png\" /></a>" + "</th>" + "</tr>" + "<tr class=\"-Pdf-head\">" + "<td>SKU</td>" + "<td>Base Unit</td>" + "<td>Pltpos(s)</td>" + "<td>CBM</td>" + "<td>Weight TON</td>" + "</tr>" + "</tbody>" + "<!-- ngRepeat: cust in _rpt.data -->" + "<tbody ng-repeat=\"cust in _rpt.data\" class=\"ng-scope\">" + "<tr>" + "<td colspan=\"6\"><strong><p class=\"ng-binding\">Test Customer</p></strong></td>" + "</tr>" + "<!-- ngRepeat: row in cust.itemGroup -->" + "<tr ng-repeat=\"row in cust.itemGroup\" ng-repeat-finished=\"rpt_ng_repeat\" class=\"ng-scope\">" + "<td><p class=\"ng-binding\">100 Test Item</p></td>" + "<td><p class=\"ng-binding\">PLT</p></td>" + "<td><p class=\"ng-binding\">68</p></td>" + "<td><p class=\"ng-binding\">68</p></td>" + "<td><p class=\"ng-binding\">68</p></td>" + "<td><p class=\"ng-binding\">0.068</p></td>" + "</tr>" + "<!-- end ngRepeat: row in cust.itemGroup -->" + "<tr class=\"-Pdf-head\">" + "<td colspan=\"3\"><p>Total</p></td>" + "<td><p class=\"ng-binding\">68</p></td>" + "<td><p class=\"ng-binding\">68</p></td>" + "<td><p class=\"ng-binding\">0.068</p></td>" + "</tr>" + "</tbody>" + "<!-- end ngRepeat: cust in _rpt.data -->" + "</table>" + "</div>"; // A minimal example provoking the exception: // String html = "<table><tr><th><h1>Test</h1></th></tr></table>"; String css = ".PDF-report{position:fixed; top:0; right:-100%; background:#fff; width:75%; height:100%; z-index:100; padding:10px; border-left:1px solid #ccc}" + " .PDF-report-active{ right: 0}" + " .PDF-report table{background:#fff; min-width:100%}" + " .PDF-report table td{ min-width:100px;}" + " .IBA-Pdf-logo img{ float:right}" + " .IBA-Pdf-head{ border-top:5px solid #000; font-weight:bold }" + " .PDF-report-holder{ height: 100 %; overflow: scroll}" + " .col-all-12{width:100%;}" + " .col-all-12, .all-col{height:auto; padding:0; margin:0; float:left}"; Directory.CreateDirectory(@"C:\Temp\test-results\xmlworker\"); var document = new Document(PageSize.A4, 10, 10, 10, 10); var writer = PdfWriter.GetInstance(document, new FileStream(@"C:\Temp\test-results\xmlworker\AjithOriginal.pdf", FileMode.Create)); document.Open(); using (var cssMemoryStream = new MemoryStream(System.Text.Encoding.UTF8.GetBytes(css))) { using (var htmlMemoryStream = new MemoryStream(System.Text.Encoding.UTF8.GetBytes(html))) { var p = XMLWorkerHelper.GetInstance(); p.ParseXHtml(writer, document, htmlMemoryStream, cssMemoryStream); } } document.Close(); } var memoryStram。同样应该清理原始代码。

无论如何,以上结果是

Screenshot

另一方面,你说

  

生成的pdf文件为空白。

并考虑到您最新的代码添加,我认为您的意思是它在某些浏览器中显示为空白。因此,它或者在StringReader htmls的某个地方丢失,或者您的浏览器不喜欢它发送给它的方式。

要验证PDF是否正确到达HttpContext.Response,您应该检查所有HttpContext.Response个实例的所有实例是否都带有PDF,例如将相应的MemoryStream的{​​{1}}值存储到文件系统中。

可能的问题:您没有显示您的方法MemoryStream实际返回ToArray()的方式;也许您使用空的pdfBytes而不是生成PDF的MemoryStream ...

只要您确定PDF确实在memoryStram受到损坏后,请再次使用浏览器进行测试。如果仍然无效,请尝试使用不同的浏览器(某些浏览器要求您设置内容长度HTTP返回标头),并尝试从浏览器保存为PDF,而不是尝试查看它。您甚至可能必须检查通过网络连接交换的数据,例如使用wireshark。这里有许多可能躲过的绊网...