将带有 iText7 的 link 添加到 PDF 的 header 或页脚
Adding a link with iText7 to the header or footer of a PDF
我目前正在尝试将 link 添加到 pdf 文档页脚的 header,但是库给出了以下错误 System.IndexOutOfRangeException:'Requested page number 0 is out of bounds.' 使用 IText7 库将 link 添加到 header 时。
将相同的 object 添加到页面的 body 可以正常工作。
用 try catch 包围代码会导致以下结果:
我在 IText7 中找不到关于此问题的任何在线代码示例,ITextSharp 中的解决方案不再适用。
我的问题是如何将外部网站的 link 添加到 pdf 的 header?当前行为是库中的错误还是有意为之?
我正在使用以下代码:
主方法,加载html,初始化文档,将object添加到header和主页面。
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();
}
事件处理程序 class 负责将 object 添加到 header。代码在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 object 的 html 文件(FooterTest.html 在 Convert() 方法中加载)
<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>
这是我关于堆栈溢出的第一个问题,因此也欢迎对问题本身的任何反馈。
您遇到的并不完全是一个错误,但在这种情况下,iText 肯定会更优雅地失败并解释。
这里的问题是,对于 Canvas
class 它实际上不知道绘图执行的页面是什么。在一般情况下 Canvas
只是内容绘制操作的高级包装器,它可以放置在任何内容流上(例如,在表单 XObject、页面内容流等中)。但是 link 是在页面级别专门定义的(通过 link 注释)。
这个问题很容易解决。我可以向您推荐两种方法。
第一种方法是通过覆盖 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
实例而不是 Canvas
。 Document
始终与页面内容一起使用,因此此处不存在已解释的问题。可以使用固定定位将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();
我目前正在尝试将 link 添加到 pdf 文档页脚的 header,但是库给出了以下错误 System.IndexOutOfRangeException:'Requested page number 0 is out of bounds.' 使用 IText7 库将 link 添加到 header 时。
将相同的 object 添加到页面的 body 可以正常工作。
用 try catch 包围代码会导致以下结果:
我在 IText7 中找不到关于此问题的任何在线代码示例,ITextSharp 中的解决方案不再适用。
我的问题是如何将外部网站的 link 添加到 pdf 的 header?当前行为是库中的错误还是有意为之?
我正在使用以下代码:
主方法,加载html,初始化文档,将object添加到header和主页面。
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();
}
事件处理程序 class 负责将 object 添加到 header。代码在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 object 的 html 文件(FooterTest.html 在 Convert() 方法中加载)
<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>
这是我关于堆栈溢出的第一个问题,因此也欢迎对问题本身的任何反馈。
您遇到的并不完全是一个错误,但在这种情况下,iText 肯定会更优雅地失败并解释。
这里的问题是,对于 Canvas
class 它实际上不知道绘图执行的页面是什么。在一般情况下 Canvas
只是内容绘制操作的高级包装器,它可以放置在任何内容流上(例如,在表单 XObject、页面内容流等中)。但是 link 是在页面级别专门定义的(通过 link 注释)。
这个问题很容易解决。我可以向您推荐两种方法。
第一种方法是通过覆盖 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
实例而不是 Canvas
。 Document
始终与页面内容一起使用,因此此处不存在已解释的问题。可以使用固定定位将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();