我试图使用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();
Run Code Online (Sandbox Code Playgroud)
错误:
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
Run Code Online (Sandbox Code Playgroud)
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>
Run Code Online (Sandbox Code Playgroud)
api电话
public ActionResult DownloadPdf(string file_name,string html)
{
var _memStream = pdfBytes(html);
var _pdfDoc = new PdfContent
{
MemoryStream = _memStream,
FileName = file_name
};
return _pdfDoc;
}
Run Code Online (Sandbox Code Playgroud)
响应
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);
}
}
Run Code Online (Sandbox Code Playgroud)
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}
Run Code Online (Sandbox Code Playgroud)
显然,iText的XMLWorker不接受标题元素(h1,h2,h3,h4,h5,或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>
Run Code Online (Sandbox Code Playgroud)
或者使它成为一个段落元素(p),不再有例外.
您可以使用缩减示例验证这一点:
<table><tr><td><h1>Test</h1></td></tr></table>
Run Code Online (Sandbox Code Playgroud)
和
<table><tr><th><p>Test</p></th></tr></table>
Run Code Online (Sandbox Code Playgroud)
两者都由XMLWorker但是处理
<table><tr><th><h1>Test</h1></th></tr></table>
Run Code Online (Sandbox Code Playgroud)
被拒绝与HTML相同的例外.
根据HTML5规范标题,表头中的元素实际上是不允许的:
4.9.10
th元素[...]
内容模型:
流内容,但没有页眉,页脚,节内容或标题内容后代.
其中标题内容被定义为
3.2.4.1.4标题内容
标题内容定义节的标题(无论是使用节内容元素明确标记,还是标题内容本身隐含).
=> h1 h2 h3 h4 h5 h6
因此,您的HTML输入不是有效的HTML,因此,iText(或任何HTML处理器)可能无法处理它.
作为参考,从您的代码派生,这是我用于测试的代码:
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();
}
Run Code Online (Sandbox Code Playgroud)
html和css中的额外空格都已从源中删除,因为我认为它们是复制到堆栈溢出时引入的工件.如果这个假设是错误的,原始的HTML和CSS应该在继续之前进行清理.
此外,删除了未使用的代码,例如var memoryStram和StringReader htmls.同样应该清理原始代码.
无论如何,上面的结果是
另一方面,你说
生成的pdf文件为空.
考虑到你最新的代码添加,我认为你的意思是它在某些浏览器中显示为空白.因此,它要么在途中丢失,要么HttpContext.Response浏览器不喜欢它发送到它的方式.
要验证PDF是否正确访问HttpContext.Response,您应检查所涉及的MemoryStream实例是否一直带有PDF,例如通过将相应MemoryStream的ToArray()值存储到文件系统.
可能的问题:您没有显示您的方法pdfBytes实际返回的方式MemoryStream; 也许你使用空memoryStram而不是memmoryStram生成PDF的...
只要您确定PDF确实HttpContext.Response已损坏,请再次使用浏览器进行测试.如果仍然无效,请尝试使用不同的浏览器(某些浏览器要求您设置内容长度HTTP返回标头),并尝试从浏览器保存为PDF,而不是尝试查看它.您甚至可能必须检查通过网络连接交换的数据,例如使用wireshark.这里有许多可能躲过的绊网......
| 归档时间: |
|
| 查看次数: |
1354 次 |
| 最近记录: |