【问题标题】:iTextSharp PDF header with HTML string C#带有 HTML 字符串 C# 的 iTextSharp PDF 标头
【发布时间】:2015-12-22 07:14:51
【问题描述】:

我正在尝试使用带有客户信息、页眉和页脚等的 iTextSharp 生成 PDF 报告。所有这些报告都已使用 EVO API 生成。作为迁移过程的一部分,我们计划使用 iTextSharp API 生成这些报告。

我需要知道是否有可能为 iTextSharp PDF 标题提供准备呈现 HTML 字符串(现有 EVO 设计接受 HTML 字符串并构建 PDF),而不是使用 PageEvents 来设计 PDFPTable 和 PDFPCell(作为数字的报告是巨大的,以避免返工)

【问题讨论】:

  • 如果一个答案足以回答您在此处发布的问题,您应该考虑接受它(单击答案左上角的勾号)。如果没有,您应该添加一条注释,在其中描述它未能这样做的原因。

标签: c# itextsharp


【解决方案1】:

我需要知道是否有可能为 iTextSharp PDF 标题提供准备呈现 HTML 字符串(现有 EVO 设计接受 HTML 字符串并构建 PDF),而不是使用 PageEvents 来设计 PDFPTable 和 PDFPCell

您必须使用 页面事件 来绘制页眉或页脚,但无需在此处显式使用 PdfPTable。您实际上可以在页面事件期间呈现 html,例如像这样:

[Test]
public void CreatePdfWithHtmlHeader()
{
    string htmlHeader = "<!DOCTYPE html><html><body><table style=\"width: 100%; border: 1px solid black;\"><tr><td>A</td><td>B</td></tr></table></body></html>";

    using (FileStream output = new FileStream(@"C:\Temp\test-results\content\html-header.pdf", FileMode.Create, FileAccess.Write))
    using (Document document = new Document(PageSize.A4))
    {
        PdfWriter writer = PdfWriter.GetInstance(document, output);
        writer.PageEvent = new HtmlPageEventHelper(htmlHeader);
        document.Open();
        document.Add(new Paragraph("1"));
        document.NewPage();
        document.Add(new Paragraph("2"));
    }
}

使用以下两个小助手类。

HtmlPageEventHelper 是一个页面事件侦听器,将给定的 html 片段绘制到页面标题中。显然它可以替代或附加写入页脚,只需使用适当的列坐标

public class HtmlPageEventHelper : PdfPageEventHelper
{
    public HtmlPageEventHelper(string html)
    {
        this.html = html;
    }

    public override void OnEndPage(PdfWriter writer, Document document)
    {
        base.OnEndPage(writer, document);

        ColumnText ct = new ColumnText(writer.DirectContent);
        XMLWorkerHelper.GetInstance().ParseXHtml(new ColumnTextElementHandler(ct), new StringReader(html));
        ct.SetSimpleColumn(document.Left, document.Top, document.Right, document.GetTop(-20), 10, Element.ALIGN_MIDDLE);
        ct.Go();
    }

    string html = null;
}

对于更复杂的 HTML 片段,您可能希望将 XMLWorkerHelper.GetInstance().ParseXHtml 调用替换为 @Skary 的答案中提供的自定义解析器调用。

ColumnTextElementHandler 是一个 IElementHandler 实现,它将内容(例如通过解析 HTML 生成)添加到 ColumnText

public class ColumnTextElementHandler : IElementHandler
{
    public ColumnTextElementHandler(ColumnText ct)
    {
        this.ct = ct;
    }

    ColumnText ct = null;

    public void Add(IWritable w)
    {
        if (w is WritableElement)
        {
            foreach (IElement e in ((WritableElement)w).Elements())
            {
                ct.AddElement(e);
            }
        }
    }
}

顺便说一句,上面的测试生成了一个包含以下内容的 PDF:

...

...


免责声明:我主要使用 Java,之前没有使用过 XmlWorker。因此,此代码可能具有相当大的改进潜力。

【讨论】:

  • 感谢您的详细回复。另一个澄清,iTextSharp HTML 到 PDF 的转换是否也支持控制级别?前任。 HTML中的文本框,按钮,会被转换成PDF吗?在我的情况下,转换后,控件不会显示在 PDF 中
  • 如我的免责声明中所述,我之前没有使用过XmlWorker。因此,我不是 iText 的 HTML 支持范围的好消息来源,并且假设您最好将其作为一个明确的新 stackoverflow 问题。不过,我知道,从这里飞过的其他问题来看,它的支持很容易扩展,参见。 @Skary 的回答中的CustomImageTagProcessor。如果某些元素尚未实现,您只需添加适当的实现即可。
【解决方案2】:

我不确定你的问题是否正确。

如果您问如何使用 iTextSharp 将 HTML 解析为 PDF,这里是我之前找到的解决方案:

        using (Document document = new Document(size))
        {
            var writer = PdfWriter.GetInstance(document, stream);

            document.Open();
            document.NewPage();
            document.Add(new Chunk(""));

            var tagProcessors = (DefaultTagProcessorFactory)Tags.GetHtmlTagProcessorFactory();
            tagProcessors.RemoveProcessor(HTML.Tag.IMG);
            tagProcessors.AddProcessor(HTML.Tag.IMG, new CustomImageTagProcessor());

            var charset = Encoding.UTF8;

            CssFilesImpl cssFiles = new CssFilesImpl();
            cssFiles.Add(XMLWorkerHelper.GetInstance().GetDefaultCSS());
            var cssResolver = new StyleAttrCSSResolver(cssFiles);
            cssResolver.AddCss(srcCssData, "utf-8", true);

            var hpc = new HtmlPipelineContext(new CssAppliersImpl(new XMLWorkerFontProvider()));
            hpc.SetAcceptUnknown(true).AutoBookmark(true).SetTagFactory(tagProcessors);
            var htmlPipeline = new HtmlPipeline(hpc, new PdfWriterPipeline(document, writer));
            var pipeline = new CssResolverPipeline(cssResolver, htmlPipeline);
            var worker = new XMLWorker(pipeline, true);
            var xmlParser = new XMLParser(true, worker, charset);

            xmlParser.Parse(new StringReader(srcFileData));

            document.Close();
        }

要使其正常工作,您需要将自定义图像处理器添加到您提供给上述转换函数的 HTML 中的内联图像:

public class CustomImageTagProcessor : iTextSharp.tool.xml.html.Image
{
    public override IList<IElement> End(IWorkerContext ctx, Tag tag, IList<IElement> currentContent)
    {
        IDictionary<string, string> attributes = tag.Attributes;
        string src;
        if (!attributes.TryGetValue(HTML.Attribute.SRC, out src))
            return new List<IElement>(1);

        if (string.IsNullOrEmpty(src))
            return new List<IElement>(1);

        if (src.StartsWith("data:image/", StringComparison.InvariantCultureIgnoreCase))
        {
            // data:[<MIME-type>][;charset=<encoding>][;base64],<data>
            var base64Data = src.Substring(src.IndexOf(",") + 1);
            var imagedata = Convert.FromBase64String(base64Data);
            var image = iTextSharp.text.Image.GetInstance(imagedata);

            var list = new List<IElement>();
            var htmlPipelineContext = GetHtmlPipelineContext(ctx);
            list.Add(GetCssAppliers().Apply(new Chunk((iTextSharp.text.Image)GetCssAppliers().Apply(image, tag, htmlPipelineContext), 0, 0, true), tag, htmlPipelineContext));
            return list;
        }
        else
        {
            return base.End(ctx, tag, currentContent);
        }
    }
}

【讨论】:

  • 当前 EVO API 接受不同的参数,例如作为 HTML 字符串的标题、作为 HTML 字符串的正文/内容和作为 HTML 字符串的页脚。最后,使用“PrepareRenderPdfPageEvent”,它整合并构建了一个完整的 PDF 模板。使用 iTextSharp,我使用 XMLParser 将正文 HTML 字符串解析为 PDF。有没有办法以同样的方式将标题 HTML 字符串解析为 PDF 标题?
  • @Sam 你能提供一个例子,说明你想从 HTML 标题添加到 PDF 标题的内容吗?
  • @Skary 很好地使用了自定义标签处理器。它可能会解决关于数据 URL 和 iText(Sharp) 的一两个尚未解决的问题。
  • 这样的东西在带有 PDFPCell 的 PDFPTable 中,(已经格式化的 HTML 内容) 1
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2013-08-01
  • 2016-09-30
  • 2010-11-22
  • 1970-01-01
  • 1970-01-01
  • 2015-05-26
  • 2012-01-20
相关资源
最近更新 更多