【问题标题】:How to add HTML headers and footers to a page?如何在页面中添加 HTML 页眉和页脚?
【发布时间】:2015-10-28 14:43:56
【问题描述】:

如何使用 itext 从 html 源向 pdf 添加标题?

目前,我们扩展了 PdfPageEventHelper 并覆盖了这些方法。工作正常,但当我到达 2+ 页时它会引发 RuntimeWorkerException。

 @Override
    void onStartPage(PdfWriter writer, Document document) {
        InputStream is = new ByteArrayInputStream(header?.getBytes());
        XMLWorkerHelper.getInstance().parseXHtml(writer, document, is);
    }

    @Override
    void onEndPage(PdfWriter writer, Document document) {
        InputStream is = new ByteArrayInputStream(footer?.getBytes());
        XMLWorkerHelper.getInstance().parseXHtml(writer, document, is);

    }

【问题讨论】:

    标签: java itext


    【解决方案1】:

    Bruno 的回答是正确的,但它并没有完全适合我,因为另一方面 XMLWorkerHelper.parsetoElementsList 无法解析某些系统字体 XMLWorkerHelper.getInstance().parseXHtml(writer, document, is); } 能够正确解析系统字体,所以我必须沿着元素处理程序的路线走下去,这是 C# 中的代码

        /// <summary>
        /// returns pdf in bytes.
        /// </summary>
        /// <param name="contentsHtml">contents.</param>
        /// <param name="headerHtml">header contents.</param>
        /// <param name="footerHtml">footer contents.</param>
        /// <returns></returns>
        public Byte[] GetPDF(string contentsHtml, string headerHtml, string footerHtml)
        {
            // Create a byte array that will eventually hold our final PDF
            Byte[] bytes;
    
            // Boilerplate iTextSharp setup here
    
            // Create a stream that we can write to, in this case a MemoryStream
            using (var ms = new MemoryStream())
            {
                // Create an iTextSharp Document which is an abstraction of a PDF but **NOT** a PDF
                using (var document = new Document(PageSize.A4, 40, 40, 120, 120))
                {
                    // Create a writer that's bound to our PDF abstraction and our stream
                    using (var writer = PdfWriter.GetInstance(document, ms))
                    {
                        // Open the document for writing
                        document.Open();
    
                        var headerElements = new HtmlElementHandler();
                        var footerElements = new HtmlElementHandler();
    
                        XMLWorkerHelper.GetInstance().ParseXHtml(headerElements, new StringReader(headerHtml));
    
                        XMLWorkerHelper.GetInstance().ParseXHtml(footerElements, new StringReader(footerHtml));
    
                        writer.PageEvent = new HeaderFooter(headerElements.GetElements(), footerElements.GetElements());
    
                        // Read your html by database or file here and store it into finalHtml e.g. a string
                        // XMLWorker also reads from a TextReader and not directly from a string
                        using (var srHtml = new StringReader(contentsHtml))
                        {
                            // Parse the HTML
                            iTextSharp.tool.xml.XMLWorkerHelper.GetInstance().ParseXHtml(writer, document, srHtml);
                        }
    
                        document.Close();
                    }
                }
    
                // After all of the PDF "stuff" above is done and closed but **before** we
                // close the MemoryStream, grab all of the active bytes from the stream
                bytes = ms.ToArray();
            }
            return bytes;
        }
    }
    

    页面事件和元素处理程序代码在这里

    public partial class HeaderFooter : PdfPageEventHelper
    {
        private ElementList HeaderElements { get; set; }
        private ElementList FooterElements { get; set; }
    
        public HeaderFooter(ElementList headerElements, ElementList footerElements)
        {
            HeaderElements = headerElements;
            FooterElements = footerElements;
        }
    
        public override void OnEndPage(PdfWriter writer, Document document)
        {
            base.OnEndPage(writer, document);
            try
            {
                ColumnText headerText = new ColumnText(writer.DirectContent);
                foreach (IElement e in HeaderElements)
                {
                    headerText.AddElement(e);
                }
                headerText.SetSimpleColumn(document.Left, document.Top, document.Right, document.GetTop(-100), 10, Element.ALIGN_MIDDLE);
                headerText.Go();
    
                ColumnText footerText = new ColumnText(writer.DirectContent);
                foreach (IElement e in FooterElements)
                {
                    footerText.AddElement(e);
                }
                footerText.SetSimpleColumn(document.Left, document.GetBottom(-100), document.Right, document.GetBottom(-40), 10, Element.ALIGN_MIDDLE);
                footerText.Go();
            }
            catch (DocumentException de)
            {
                throw new Exception(de.Message);
            }
        }
    }
    
    public class HtmlElementHandler : IElementHandler
    {
        public ElementList Elements { get; set; }
    
        public HtmlElementHandler()
        {
            Elements = new ElementList();
        }
    
        public ElementList GetElements()
        {
            return Elements;
        }
    
        public void Add(IWritable w)
        {
            if (w is WritableElement)
            {
                foreach (IElement e in ((WritableElement)w).Elements())
                {
                    Elements.Add(e);
                }
            }
        }
    }
    

    【讨论】:

      【解决方案2】:

      一般禁止onStartPage() 事件中添加内容。 禁止onEndPage() 中的document 对象添加内容。您应该使用PdfWriter, NOT 文档在onEndPage() 方法中添加页眉和页脚。另外:一遍又一遍地解析 HTML 会浪费大量 CPU。

      请查看HtmlHeaderFooter 示例。

      它有两个 HTML 的 sn-ps,一个用于页眉,一个用于页脚。

      public static final String HEADER =
          "<table width=\"100%\" border=\"0\"><tr><td>Header</td><td align=\"right\">Some title</td></tr></table>";
      public static final String FOOTER =
          "<table width=\"100%\" border=\"0\"><tr><td>Footer</td><td align=\"right\">Some title</td></tr></table>";
      

      请注意,有比使用 HTML 更好的方式来描述页眉和页脚,但也许这是您的要求之一,所以我不会问您为什么不使用 @ 中解释的任何方法987654322@。顺便说一句:解决问题所需的所有信息也可以在free ebook 中找到,因此您可能需要下载它...

      我们将在页面事件中只读取一次这些 HTML sn-ps,然后我们将在每个页面上一遍又一遍地渲染元素:

      public class HeaderFooter extends PdfPageEventHelper {
          protected ElementList header;
          protected ElementList footer;
          public HeaderFooter() throws IOException {
              header = XMLWorkerHelper.parseToElementList(HEADER, null);
              footer = XMLWorkerHelper.parseToElementList(FOOTER, null);
          }
          @Override
          public void onEndPage(PdfWriter writer, Document document) {
              try {
                  ColumnText ct = new ColumnText(writer.getDirectContent());
                  ct.setSimpleColumn(new Rectangle(36, 832, 559, 810));
                  for (Element e : header) {
                      ct.addElement(e);
                  }
                  ct.go();
                  ct.setSimpleColumn(new Rectangle(36, 10, 559, 32));
                  for (Element e : footer) {
                      ct.addElement(e);
                  }
                  ct.go();
              } catch (DocumentException de) {
                  throw new ExceptionConverter(de);
              }
          }
      }
      

      你看到我们用来添加从 XML Worker 获得的Element 对象的机制了吗?我们创建一个ColumnText 对象,它将写入writer直接内容(禁止使用document)。我们定义了一个Rectangle 并使用go() 来渲染元素。

      结果显示在html_header_footer.pdf

      【讨论】:

      • 嗨,我在解析这个值时遇到了困难:
        页脚 一些标题
        有什么帮助吗?
      • @Prabhat 发布一个问题,解释您遇到的困难。评论不应用于提出或回答新问题。
      • 布鲁诺,我已经发布了问题stackoverflow.com/questions/37767027/…,我卡在这里,请你回答。谢谢
      • 我在编写以下代码时出错:“ColumnText ct = new ColumnText(writer.getDirectContent());”在“作家”之后,我没有得到“getDirectContent”。
      • @chirag 您决定不升级到 iText 7,而是坚持使用 iText 5。您能否详细说明为什么选择使用不再受支持的版本? “不再支持”的概念意味着不再回答有关该版本的问题,除非您是付费客户。您是付费客户吗?
      猜你喜欢
      • 2021-03-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-09-05
      • 2020-07-29
      相关资源
      最近更新 更多