我正在开发的应用程序使用 itextsharp 库从 html 文件生成 pdf 报告。显然,当生成大表时,itextsharp 会分配大量内存(对于 200KB 的文件,大约需要 300 MB)。解决此问题的方法是将表格一点一点地添加到文档中(因此表格中的所有现有数据都将被刷新),如下面的链接所述:
问题:从现有的 html 文件生成 pdf 时,如何分步添加 pdfptable?
这是我的代码:
public byte[] GetReportPdf(string template, string cssString)
{
byte[] result;
using (var stream = new MemoryStream())
{
using (
var doc = new Document(
this.Settings.Size,
this.Settings.Margins.Left,
this.Settings.Margins.Right,
this.Settings.Margins.Top,
this.Settings.Margins.Bottom))
{
using (var writer = PdfWriter.GetInstance(doc, stream))
{
// adding the page event, or null
writer.PageEvent = this.Settings.PageEvent;
doc.Open();
// CSS
var cssResolver = new StyleAttrCSSResolver();
using (var cssStream = new MemoryStream(Encoding.UTF8.GetBytes(cssString)))
{
var cssFile = XMLWorkerHelper.GetCSS(cssStream);
cssResolver.AddCss(cssFile);
}
// HTML
var fontProvider = new XMLWorkerFontProvider(XMLWorkerFontProvider.DONTLOOKFORFONTS);
var cssAppliers = new CssAppliersImpl(fontProvider);
var htmlContext = new HtmlPipelineContext(cssAppliers);
htmlContext.SetTagFactory(Tags.GetHtmlTagProcessorFactory());
// pipelines
var pdf = new PdfWriterPipeline(doc, writer);
var html = new HtmlPipeline(htmlContext, pdf);
var css = new CssResolverPipeline(cssResolver, html);
// XML worker
var worker = new XMLWorker(css, true);
var parser = new XMLParser(worker);
using (var stringReader = new StringReader(template))
{
parser.Parse(stringReader);
}
doc.Close();
}
}
result = stream.ToArray();
}
return result;
备注:
- 前面链接中的解决方案不使用 html 来创建 pdf
- 描述的步骤是:将表格完成属性设置为 false,将每 50 个表格行添加到文档中,将表格完成属性设置为 true。
- 使用 AbstractTagProcessor,我设法在解析 html 时设置了 table complete 属性,但没有找到关于如何在生成表时触发添加表的选项。
- itextsharp 版本 5.5.10.0
- itextsharp.xmlworker 版本 5.5.10.0
var tagFactory = Tags.GetHtmlTagProcessorFactory();
tagFactory.AddProcessor(new TableTagProcessor(doc), new string[]{"table"});
public class TableTagProcessor : iTextSharp.tool.xml.html.table.Table{
public override IList<IElement> Start(IWorkerContext ctx, Tag tag)
{
var result = base.Start(ctx, tag);
foreach (PdfPTable table in result.OfType<PdfPTable>())
{
table.Complete = false;
}
return result;
}
public override IList<IElement> End(IWorkerContext ctx, Tag tag, IList<IElement> currentContent)
{
var result = base.End(ctx, tag, currentContent);
foreach (PdfPTable table in result.OfType<PdfPTable>())
{
table.Complete = true;
}
return result;
}}