【问题标题】:Adding a link with iText7 to the header or footer of a PDF将带有 iText7 的链接添加到 PDF 的页眉或页脚
【发布时间】:2018-12-03 10:06:04
【问题描述】:

我目前正在尝试添加指向 pdf 文档页脚页眉的链接,但是库给出以下错误 System.IndexOutOfRangeException: 'Requested page number 0 is out of bounds.' 当使用 IText7 库将链接添加到标题。

将相同的对象添加到页面正文可以正常工作。 用 try catch 包围代码会导致以下结果:

我在 IText7 中找不到任何关于此问题的在线代码示例,ITextSharp 中的解决方案不再适用。

我的问题是如何将外部网站的链接添加到 pdf 的标题中?当前行为是库中的错误还是有意的?

我正在使用以下代码:

main方法,加载html,初始化文档,添加对象到页眉和主页面。

public void Convert()
{
    // Initialize template
    IList<IElement> templateElements = HtmlConverter.ConvertToElements(File.ReadAllText("FooterTest.html"));

    // Initialize document
    PdfWriter pdfWriter = new PdfWriter("Output.pdf");
    PdfDocument pdfDocument = new PdfDocument(pdfWriter);
    Document document = new Document(pdfDocument);
    document.SetTopMargin(100);

    // Adding the header object to the header and the main body
    pdfDocument.AddEventHandler(PdfDocumentEvent.START_PAGE, new PdfHeader((IBlockElement)templateElements[0], document));
    document.Add((IBlockElement)templateElements[0]);

    document.Close();
}

负责将对象添加到标头的事件处理程序类。代码在try-catch中给出了上面提到的错误

public class PdfHeader : IEventHandler
{
    private readonly IBlockElement footer;
    private readonly Document doc;

    public PdfHeader(IBlockElement footer, Document doc)
    {
        this.doc = doc;
        this.footer = footer;
    }

    public void HandleEvent(Event headerEvent)
    {
        PdfDocumentEvent docEvent = (PdfDocumentEvent)headerEvent;
        PdfDocument pdf = docEvent.GetDocument();
        PdfPage page = docEvent.GetPage();
        Rectangle pageSize = page.GetPageSize();
        PdfCanvas pdfCanvas = new PdfCanvas(page.GetLastContentStream(), page.GetResources(), pdf);
        Rectangle rectangle = new Rectangle(
            pdf.GetDefaultPageSize().GetX() + doc.GetLeftMargin(),
            pdf.GetDefaultPageSize().GetTop() - 80,
            page.GetPageSize().GetWidth() - doc.GetLeftMargin() - doc.GetRightMargin(),
            50);

        //Below is the code where the error is produced.
        try
        {
            new Canvas(pdfCanvas, pdf, rectangle).Add(footer);

        }
        catch { }
    }
}

包含 header 对象的 html 文件(在 Convert() 方法中加载的FooterTest.html)

<html>
    <body>
        <table>
            <tr>
                <td>
                This is a some text not containing a link.
                </td>
            </tr>
            <tr>
                <td>
                This text contains a link to <a href="https://www.google.com">Google</a> to demonstrate the issue.
                </td>
            </tr>
        </table>
    </body>
</html>

这是我关于堆栈溢出的第一个问题,因此也感谢您对问题本身的任何反馈。

【问题讨论】:

    标签: c# itext itext7


    【解决方案1】:

    您遇到的并不完全是一个错误,但是在这种情况下,iText 肯定会更优雅地失败并且更容易解释。

    这里的问题是,对于Canvas 类,实际上不知道执行绘图的页面是什么。一般情况下,Canvas 只是内容绘制操作的高级包装器,可以放置在任何内容流上(例如,在表单 XObject、页面内容流等中)。但是,链接是在页面级别专门定义的(通过链接注释)。

    解决这个问题是相当容易的。我可以建议你两种方法。

    第一种方法是通过覆盖 CanvasRenderer 来解决问题:

    // set the custom renderer:
    Canvas canvas = new Canvas(pdfCanvas, pdf, rectangle);
    canvas.setRenderer(new PageCanvasRenderer(canvas, page));
    canvas.add(footer);
    
    ...
    
    private static class PageCanvasRenderer extends CanvasRenderer {
        private final PdfPage page;
    
        public PageCanvasRenderer(Canvas canvas, PdfPage page) {
            super(canvas);
            this.page = page;
        }
    
        @Override
        protected LayoutArea updateCurrentArea(LayoutResult overflowResult) {
            if (currentArea == null) {
                currentArea = new RootLayoutArea(canvas.getPdfDocument().getPageNumber(page), canvas.getRootArea().clone());
            }
            return currentArea;
        }
    }
    

    第二种方法是使用Document 实例而不是CanvasDocument 始终与页面内容一起使用,因此此处不存在已解释的问题。您可以使用固定定位将内容放置在 PdfHeader 中:

    替换

    new Canvas(pdfCanvas, pdf, rectangle).Add(footer);
    

    Document document = new Document(pdf);
    
    Div canvas = new Div().setFixedPosition(pdf.getPageNumber(page), rectangle.getLeft(), rectangle.getBottom(), rectangle.getWidth());
    canvas.add(footer);
    
    document.add(canvas);
    // Don't close document itself! It would close the PdfDocument!
    document.getRenderer().close();
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-07-23
      • 1970-01-01
      • 2020-07-04
      • 2023-03-12
      • 2015-12-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多