PDFBox извлекает бланки из PDF, зашифрованные без пароля - PullRequest
0 голосов
/ 28 августа 2018

Я использую PDFBox для извлечения текста из форм, и у меня есть PDF, который не зашифрован паролем, но PDFBox говорит, что он зашифрован. Я подозреваю, что это какая-то «функция» Adobe, потому что когда я ее открываю, она говорит (ЗАЩИЩЕНО), в то время как другие PDF-файлы, с которыми у меня нет проблем, этого не делают. isEncrypted() возвращает true, поэтому, несмотря на отсутствие пароля, он как-то защищен.

Я подозреваю, что он не расшифровывается должным образом, так как он может извлекать текстовые подсказки формы, но не сами ответы. В приведенном ниже коде он извлекает Address (Street Name and Number) и City из образца PDF, но не ответ между ними.

Я использую PDFBox 2.0, но я также пробовал 1.8.

Я перепробовал все методы расшифровки, которые я могу найти для PDFBox, включая устаревшие (почему бы и нет). Я получаю тот же результат, что и вообще не пытаюсь расшифровать, только подсказки Address и City.

Поскольку PDF является абсолютным кошмаром, которым они являются, этот PDF, вероятно, был создан каким-то нестандартным способом. Любая помощь в выявлении этого и возобновлении работы приветствуется.

Образец PDF

import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.pdmodel.PDPageTree;
import org.apache.pdfbox.pdmodel.encryption.StandardDecryptionMaterial;
import org.apache.pdfbox.text.PDFTextStripperByArea;
import java.io.File;
import org.apache.pdfbox.pdmodel.PDPage;
import java.awt.Rectangle;
import java.util.List;


class Scratch {

    private static float pwidth;
    private static float pheight;

    private static int widthByPercent(double percent) {
        return (int)Math.round(percent * pwidth);
    }

    private static int heightByPercent(double percent) {
        return (int)Math.round(percent * pheight);
    }

    public static void main(String[] args) {
        try {
            //Create objects
            File inputStream = new File("ocr/TestDataFiles/i-9_08-07-09.pdf");

            PDDocument document = PDDocument.load(inputStream);

            // Try every decryption method I've found
            if(document.isEncrypted()) {

                // Method 1
                document.decrypt("");

                // Method 2
                document.openProtection(new StandardDecryptionMaterial(""));

                // Method 3
                document.setAllSecurityToBeRemoved(true);

                System.out.println("Removed encryption");
            }

            PDFTextStripperByArea stripper = new PDFTextStripperByArea();

            //Get the page with data on it
            PDPageTree allPages = document.getDocumentCatalog().getPages();
            PDPage page = allPages.get(3);

            pheight = page.getMediaBox().getHeight();
            pwidth = page.getMediaBox().getWidth();

            Rectangle LastName = new Rectangle(widthByPercent(0.02), heightByPercent(0.195), widthByPercent(0.27), heightByPercent(0.1));
            stripper.addRegion("LastName", LastName);
            stripper.setSortByPosition(true);
            stripper.extractRegions(page);
            List<String> regions = stripper.getRegions();

            System.out.println(stripper.getTextForRegion("LastName"));

        } catch (Exception e){
            System.out.println(e.getMessage());
        }
    }
}

1 Ответ

0 голосов
/ 28 августа 2018

Комментарий Бруноса объясняет, почему PDF-файл зашифрован, даже если вам не нужно вводить пароль:

PDF может быть зашифрован двумя паролями: пароль пользователя и пароль владельца . Если PDF-файл зашифрован с помощью пароля user , вы не сможете открыть документ в программе просмотра PDF без ввода этого пароля. Если PDF-файл зашифрован только с помощью пароля owner , каждый может открыть PDF-файл без этого пароля, но могут быть некоторые ограничения. Вы можете распознать PDF-файлы, зашифрованные с помощью пароля владельца, поскольку в Adobe Reader упоминается «ЗАЩИЩЕНО».

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

document.decrypt("");

(Кстати, этот «метод 1» точно такой же, как ваш «метод 2»

document.openProtection(new StandardDecryptionMaterial(""));

плюс некоторые исключения.)


Комментарий Тилмана подразумевает причину, по которой вы не извлекаете значения формы: ваш код использует PDFTextStripperByArea для извлечения текста, но это извлечение текста только извлекает фиксированное содержимое страницы , а не содержимое аннотаций , плавающих на этой странице.

Содержимое, которое вы хотите извлечь, - это содержимое полей формы, виджеты которых являются аннотациями.

Предложение Тильмана

doc.getDocumentCatalog().getAcroForm().getField("form1[0].#subform[3].address[0]").getValueAsString()

показывает, как извлечь значение поля формы, имя которого вы знаете, "form1[0].#subform[3].address[0]" в этом случае. Если вы не знаете имя поля, из которого вы хотите извлечь содержимое, у объекта PDAcroForm, возвращаемого doc.getDocumentCatalog().getAcroForm(), есть ряд других методов для доступа к содержимому поля.


Кстати, имя поля, например "form1[0].#subform[3].address[0]" в определении AcroForm , указывает на еще одну особенность вашего PDF: на самом деле оно содержит два определения формы , ядро ​​PDF * 1054 Определение * AcroForm и более независимое определение XFA . Оба описывают одну и ту же визуальную форму. Такая форма PDF называется гибридной формой PDF .

Преимущество гибридных форм заключается в том, что их можно просматривать и заполнять с помощью инструментов PDF, которые знают только AcroForm форм (которые по сути являются всеми программами, кроме Adobe), в то время как инструменты PDF с поддержкой XFA (в основном только Adobe) программное обеспечение) может использовать дополнительные функции XFA.

Недостаток гибридных форм заключается в том, что если они заполнены с помощью инструмента без поддержки XFA, обновляется только информация AcroForm , а информация XFA остается прежней. Таким образом, гибридный документ может содержать разные данные для одного и того же поля ...

...