Как узнать, в какое поле изображения в PDF вставлено изображение, а в какое нет изображений, прикрепленных в PDFbox 1.8.11? - PullRequest
0 голосов
/ 09 июля 2019

У меня есть PDF, в котором есть поля изображения.Я не использую PDPushButton с javascript для прикрепления изображений, потому что, если я это сделаю, верхний слой кнопки будет заменен на изображение, которое я прикрепляю, а это не то, что я хочу.Поэтому я явно использую ImageField, который доступен в Adobe LiveCycle Designer.Я могу извлечь файлы, прикрепленные к нему, используя PDFBox, но я не могу найти какой-либо способ увидеть, какие поля изображения имеют прикрепленные к ним файлы, а какие нет.Например, если у меня есть следующий код:

ImageField [1], ImageField [2], ImageField [3]

Я хочу увидеть что-то вроде ImageField [1]: null, ImageField[2]: true, ImageField [3]: true enter code here

и т. Д. При условии, что к ImageField [2] и ImageField [3] прикреплены изображения.

Ниже приведен код, который яработал над:

У меня есть константа:

Затем я перебираю весь набор имен полей изображения и вижу, какое поле является экземпляром PDXObjectImage, а затем, если это PDXObjectImage, тоЯ проверяю, является ли этот object.getRGBImage (). GetHeight ()> 0 при условии, что только загруженные файлы имеют высоту> 1, что означает, что файл был прикреплен.

частная статическая строка [] IMAGE_FIELD_ROW = {"ImageField1 [0]", "ImageField2 [0]", ....} => 100 строк строковых значений, таких как "ImageField3 [0]", "ImageField4 [0] ", ... и т. Д.

    for(int i = 0; i<IMAGE_FIELD_ROW.length; i++)
    {
        if(field.getPartialName().equals(IMAGE_FIELD_ROW[i]))
        {
            Map<String, PDAppearanceStream> stateAppearances = field.getWidget().getAppearance().getNormalAppearance();
            for (Map.Entry<String, PDAppearanceStream> entry: stateAppearances.entrySet())
            {
                PDAppearanceStream appearance = entry.getValue();
                PDResources resources = appearance.getResources();
                 if (resources == null)
                     return;
                 Map<String, PDXObject> xObjects = resources.getXObjects();
                 if (xObjects == null)
                     return;

                 for (Map.Entry<String, PDXObject> entryNew : xObjects.entrySet())
                 {
                     PDXObject xObject = entryNew.getValue();
                     System.out.println("printing out the xobject name: "+ entryNew.getKey());


                     if (xObject instanceof PDXObjectForm)
                     {

                         PDXObjectForm form = (PDXObjectForm)xObject;
                         PDResources resources2 = form.getResources();
                         if (resources2 == null)
                             return;
                         Map<String, PDXObject> xObjects2 = resources2.getXObjects();
                         if (xObjects2 == null)
                         {
                             return;
                         }
                         for (Map.Entry<String, PDXObject> entry2 : xObjects2.entrySet())
                         {

                             PDXObject xObject2 = entry2.getValue();

                             if (xObject2 instanceof PDXObjectForm)
                             {
                                 continue;
                             }
                             else if (xObject2 instanceof PDXObjectImage)
                             {
                                 PDXObjectImage ig = (PDXObjectImage)xObject2;
                                 if(ig.getRGBImage().getHeight() >  0)
                                 {
                                     images.put(field.getPartialName(), "true");
                                 }
                                 else
                                 {
                                     images.put(field.getPartialName(), null);
                                 }

                                 //imageIds.add(imageId);
                             }
                             else
                             {
                                continue;
                             }

                     }

                 }
            }

        }
        }
    }

Изображения - это переменная карты: Mapimages.

Также мой кодовый файл большой, поэтому я не хотел никого перегружать, вставляя весь файл.Ниже приведена ссылка на образец файла PDF, который я использую:

https://www.dropbox.com/s/g2wqm8ipsp8t8l5/GSA%20500%20PDF_v4.pdf?dl=0

1 Ответ

0 голосов
/ 18 июля 2019

Ваш PDF является гибридным документом AcroForm / XFA;где часть XFA использует поля с пользовательским интерфейсом imageEdit, часть AcroForm использует поля кнопок.

Таким образом, она позволяет двумя способами проверить, установлено ли поле изображения: Либо вы смотрите на кнопки AcroForm и просматриваетеих появления для изображений, или вы извлекаете XFA XML и проверяете это.

Проверка XFA XML

Изначально я пропустил версию PDFBox в заголовке вопроса и реализовал ее для PDFBox2.0.x.Как выясняется, однако, идентичный код может использоваться для PDFBox 1.8.11, могут быть выброшены только некоторые дополнительные исключения и, следовательно, должны быть рассмотрены.

Последний вариант, проверка XFAXML на самом деле немного проще для документа под рукой.Просто найдите в XML элемент с указанным именем и проверьте его содержимое.В качестве дополнительной проверки работоспособности можно проверить атрибут типа содержимого элемента:

boolean isFieldFilledXfa(Document xfaDom, String fieldName) {
    NodeList fieldElements = xfaDom.getElementsByTagName(fieldName);
    for (int i = 0; i < fieldElements.getLength(); i++) {
        Node node = fieldElements.item(i);
        if (node instanceof Element) {
            Element element = (Element) node;
            if (element.getAttribute("xfa:contentType").startsWith("image/")) {
                return element.getTextContent().length() > 0;
            }
        }
    }
    return false;
}

( CheckImageFieldFilled вспомогательный метод)

С его помощьюВы можете проверить свой документ:

PDDocument document = PDDocument.load(SOURCE);
PDAcroForm acroForm = document.getDocumentCatalog().getAcroForm();
Document xfaDom = acroForm.getXFA().getDocument();

System.out.println("Filled image fields from ImageField1..ImageField105:");
for (int i=1; i < 106; i++) {
    if (isFieldFilledXfa(xfaDom, "ImageField" + i)) {
        System.out.printf("* ImageField%d\n", i);
    }
}

( CheckImageFieldFilled метод испытания testCheckXfaGsa500Pdf_v4)

Выход:

Filled image fields from ImageField1..ImageField105:
* ImageField1
* ImageField3
* ImageField6

Проверка внешнего вида AcroForm

Реализация здесь работает только как есть для PDFBox 2.0.x.Структура классов синтаксического анализатора потока контента была значительно переработана в 2.0.0, что сделало бэкпорт этого кода на 1.8.xa немного утомительным.

Чтобы проверить, действительно ли появление кнопки действительно показывает изображение (и не только имеет изображение в своих ресурсах ), можно использовать простой подкласс PDFGraphicsStreamEngine, например:

public class WidgetImageChecker extends PDFGraphicsStreamEngine
{
    public WidgetImageChecker(PDAnnotationWidget widget) {
        super(widget.getPage());
        this.widget = widget;
    }

    public boolean hasImages() throws IOException {
        count = 0;
        PDAppearanceStream normalAppearance = widget.getNormalAppearanceStream();
        processChildStream(normalAppearance, widget.getPage());
        return count != 0;
    }

    @Override
    public void drawImage(PDImage pdImage) throws IOException {
        count++;
    }

    @Override
    public void appendRectangle(Point2D p0, Point2D p1, Point2D p2, Point2D p3) throws IOException { }

    @Override
    public void clip(int windingRule) throws IOException { }

    @Override
    public void moveTo(float x, float y) throws IOException {  }

    @Override
    public void lineTo(float x, float y) throws IOException { }

    @Override
    public void curveTo(float x1, float y1, float x2, float y2, float x3, float y3) throws IOException {  }

    @Override
    public Point2D getCurrentPoint() throws IOException { return null; }

    @Override
    public void closePath() throws IOException { }

    @Override
    public void endPath() throws IOException { }

    @Override
    public void strokePath() throws IOException { }

    @Override
    public void fillPath(int windingRule) throws IOException { }

    @Override
    public void fillAndStrokePath(int windingRule) throws IOException { }

    @Override
    public void shadingFill(COSName shadingName) throws IOException { }

    final PDAnnotationWidget widget;
    int count = 0;
} 

( CheckImageFieldFilled вспомогательный класс)

С его помощью вы можете создать метод проверки следующим образом:

boolean isFieldFilledAcroForm(PDAcroForm acroForm, String fieldName) throws IOException {
    for (PDField field : acroForm.getFieldTree()) {
        if (field instanceof PDPushButton && fieldName.equals(field.getPartialName())) {
            for (final PDAnnotationWidget widget : field.getWidgets()) {
                WidgetImageChecker checker = new WidgetImageChecker(widget);
                if (checker.hasImages())
                    return true;
            }
        }
    }
    return false;
}

( CheckImageFieldFilled вспомогательный метод)

и используйте его следующим образом:

PDDocument document = PDDocument.load(SOURCE);
PDAcroForm acroForm = document.getDocumentCatalog().getAcroForm();

System.out.println("Filled image fields (AcroForm) from ImageField1..ImageField105:");
for (int i=1; i < 106; i++) {
    if (isFieldFilledAcroForm(acroForm, "ImageField" + i + "[0]")) {
        System.out.printf("* ImageField%d\n", i);
    }
}

( CheckImageFieldFilled test testCheckAcroFormGsa500Pdf_v4)

Вывод, как и выше:

Filled image fields (AcroForm) from ImageField1..ImageField105:
* ImageField1
* ImageField3
* ImageField6
...