iTextSharp PDF header 与 HTML 字符串 C#

iTextSharp PDF header with HTML string C#

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

我需要知道是否有可能向 iTextSharp PDF header 提供准备渲染 HTML 字符串(现有 EVO 设计接受 HTML 字符串并构建 PDF),而不是使用 PageEvents 来设计 PDFPTable 和 PDFPCell(因为报告的数量很大并且避免返工)

我不确定是否理解你的问题。

如果您询问如何使用 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);
        }
    }
}

I need to know if there is any possibility to provide a ready to render HTML string to iTextSharp PDF header (Existing EVO design accepts HTML string and build PDF), instead of using PageEvents to design with PDFPTable and 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。因此,此代码可能具有相当大的改进潜力。