Получить страницу из найденного поля формы AcroForm

У меня есть существующий PDF-файл, который я хочу открыть и добавить контент на страницу, где включен конкретный PDField (или конкретно PDTerminalField, не то чтобы я думаю, что это имеет значение). Он может быть на первой или любой более поздней странице.
Я знаю имя поля, и с его помощью я могу найти его и даже получить размеры и положение на этой странице (DRectangle mediabox = new PDRectangle((COSArray) fieldDict.getDictionaryObject(COSName.RECT));)

Однако я не могу найти способ узнать номер / индекс страницы, на которой он находится, поэтому могу писать на правильной странице.

PDAcroForm acroForm = pdfDocument.getDocumentCatalog().getAcroForm();
PDField docField = acroForm.getField("the_coolest_field");

int page = docField.???  // This is the missing part.


PDPageContentStream contentStream = new PDPageContentStream(pdfDocument, 
pdfDocument.getPage(page), PDPageContentStream.AppendMode.APPEND, true);
// now write something on the page where the field is in.

person luckydonald    schedule 25.11.2020    source источник


Ответы (1)


Используя подсказки, приведенные в этот комментарий Я мог бы создать карту, содержащую имена полей и (последнюю) страницу, на которой это произошло.

HashMap<String, Integer> formFieldPages = new HashMap<>();
for (int page_i = 0; page_i < pdf_document.getNumberOfPages(); page_i++) {
    List<PDAnnotation> annotations = pdf_document.getPage(page_i).getAnnotations(); //
    for (PDAnnotation annotation: annotations) {
        if (!(annotation instanceof PDAnnotationWidget)) {
            System.err.println("Unknown annotation type " + annotation.getClass().getName() + ": " + annotation.toString());
            continue;
        }
        String name = ((PDAnnotationWidget)annotation).getCOSObject().getString(COSName.T);
        if (name == null) {
            System.err.println("Unknown widget name: " + annotation.toString());
            continue;
        }
        // make sure the field does not exists in the map
        if (formFieldPages.containsKey(name)) {
            System.err.println("Duplicated widget name, overwriting previous page value " + formFieldPages.get(name) + " with newly found page " + page_i + ": " + annotation.toString());
        }
        formFieldPages.put(name, page_i);
    }
}

Теперь поиск по странице так же прост, как

int page = formFieldPages.get(docField.getPartialName());

Обратите внимание, что это может вызвать исключение NullPointerException, если этот виджет не существует по какой-либо причине.


Предыдущий ответ ниже. Кажется, я ошибался в этом подходе, но сохраню его для справки:

Я нашел элемент /P, который, похоже, может быть страницей:

int page = (int)currentField.getCOSObject().getCOSObject(COSName.P).getObjectNumber();
page = page - 5; // I couldn't figure out why it's off by 4, but tests showed that the actual PDF page 1 (index [0]) is represented by `\P {4, 0}`, page 2 ([1]) is called "5", page 3 ([2]) is "6", etc.
person luckydonald    schedule 25.11.2020