Добавление ссылки с iText7 в верхний или нижний колонтитул PDF - PullRequest
0 голосов
/ 03 декабря 2018

В настоящее время я пытаюсь добавить ссылку в верхний колонтитул PDF-документа, однако библиотека выдает следующую ошибку System.IndexOutOfRangeException: 'Запрошенная страница № 0 выходит за границы.' при добавленииссылка на заголовок с использованием библиотеки IText7 .

Добавление одного и того же объекта в тело страницы работает нормально.Окружение кода попыткой перехвата приводит к следующему: Image of pdf output

Я не смог найти в Интернете никаких примеров кода, касающихся этой проблемы, в IText7 , решения в ITextSharp больше не применимы.

Мой вопрос: как добавить ссылку на внешний сайт в заголовок PDF?Является ли текущее поведение ошибкой в ​​библиотеке или предназначено?

Я использую следующий код:

Основной метод, загрузка 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 { }
    }
}

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>

Это мой первый вопрос о переполнении стека, поэтому любые отзывы о самом вопросе также приветствуются.

1 Ответ

0 голосов
/ 10 декабря 2018

То, с чем вы столкнулись, не является полной ошибкой, однако в этом случае 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 вместо 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();
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...