PDFBox не печатает поля формы - PullRequest
0 голосов
/ 03 февраля 2019

Я пытаюсь напечатать постобработанный (заполненный) PDF-шаблон, который был создан в LibreOffice и содержит заполненное поле формы.

PDFBox svn хорош и имеет много примеров, как это сделать.Получить PDF и AcroFormat очень просто, и даже редактирование и сохранение измененного PDF на диск работает, как и ожидалось.Но это не моя цель.Мне нужен PDF-файл, в котором поля заполнены, а затем удалены с оставшимся только текстом.

Я перепробовал все в stackoverflow, касающемся PDFBox, от выравнивания акроформы до установки свойств readonly для полей и другой мета-информации,установлены необходимые шрифты и многое другое.Каждый раз, когда я печатал PDF в файл, текст (отредактированный и не отредактированный), который находился в текстовом поле, исчезал, а текстовые поля исчезали.

Но затем я попытался создать PDF с нуля с PDFBox, и печать работает, как и ожидалось.Текстовые поля находились в сгенерированном шаблоне, а печатный файл pdf содержал нужный мне текст с удалением соответствующих форм.Поэтому я использовал PDF Debugger из PDFBox для анализа структуры PDF и заметил, что в предварительном просмотре отладчика мой PDF не содержит текст в текстовом поле, экспортированном из LibreOffice.НО в древовидной структуре отчетливо видна аннотация PDF (/ DV и / V), которая выглядит тихо, как и созданная версия pdfbox, которая работает.

Для тестирования я создал простой pdf с одним текстовым полем.с именем «тест» и содержанием «Foobar».Кроме того, фон и цвет рамки были изменены, чтобы увидеть, было ли что-нибудь успешно распечатано.

    PDDocument document = null;
    try {
        document = PDDocument.load(new File("<filepath>\\<filename>"));
    } catch (final InvalidPasswordException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    } catch (final IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }

    PrintFields.createDummyPDF("<filepath>\\<filename>");
    PrintFields.printFields(document); //debug output

    //Getting pdf meta infos
    final PDDocumentCatalog docCatalog = document.getDocumentCatalog();
    final PDAcroForm acroForm = docCatalog.getAcroForm();
    docCatalog.setAcroForm(acroForm);

    //setting the appearance
    final PDFont font = PDType1Font.HELVETICA;
    final PDResources resources = new PDResources();
    resources.put(COSName.getPDFName("Helv"), font);
    acroForm.setDefaultResources(resources);
    String defaultAppearanceString = "/Helv 0 Tf 0 g";
    acroForm.setDefaultAppearance(defaultAppearanceString);

    for(final PDField f : acroForm.getFields()) {
        if(f instanceof PDTextField) {
             defaultAppearanceString = "/Helv 12 Tf 0 0 1 rg";
            final List<PDAnnotationWidget> widgets = ((PDTextField)f).getWidgets();
            widgets.get(0).setAppearanceState(defaultAppearanceString);             
        }
    }

    for(final PDField f : acroForm.getFields()) {
        f.setReadOnly(true);
    }

    // save modified pdf to file 
    document.save("<filepath>\\<filename>");

    //print to file (to pdf)
    if (job.printDialog()) {
        try {
            // Desktop.getDesktop().print();
            job.print();
        } catch (final PrinterException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }


// copied from pdfbox examples
public static void createDummyPDF(final String path) throws IOException
{
    // Create a new document with an empty page.
    try (PDDocument document = new PDDocument())
    {
        final PDPage page = new PDPage(PDRectangle.A4);
        document.addPage(page);

        // Adobe Acrobat uses Helvetica as a default font and
        // stores that under the name '/Helv' in the resources dictionary
        final PDFont font = PDType1Font.HELVETICA;
        final PDResources resources = new PDResources();
        resources.put(COSName.getPDFName("Helv"), font);

        // Add a new AcroForm and add that to the document
        final PDAcroForm acroForm = new PDAcroForm(document);
        document.getDocumentCatalog().setAcroForm(acroForm);

        // Add and set the resources and default appearance at the form level
        acroForm.setDefaultResources(resources);

        // Acrobat sets the font size on the form level to be
        // auto sized as default. This is done by setting the font size to '0'
        String defaultAppearanceString = "/Helv 0 Tf 0 g";
        acroForm.setDefaultAppearance(defaultAppearanceString);

        // Add a form field to the form.
        final PDTextField textBox = new PDTextField(acroForm);
        textBox.setPartialName("SampleField");

        // Acrobat sets the font size to 12 as default
        // This is done by setting the font size to '12' on the
        // field level.
        // The text color is set to blue in this example.
        // To use black, replace "0 0 1 rg" with "0 0 0 rg" or "0 g".
        defaultAppearanceString = "/Helv 12 Tf 0 0 1 rg";
        textBox.setDefaultAppearance(defaultAppearanceString);

        // add the field to the acroform
        acroForm.getFields().add(textBox);

        // Specify the widget annotation associated with the field
        final PDAnnotationWidget widget = textBox.getWidgets().get(0);
        final PDRectangle rect = new PDRectangle(50, 750, 200, 50);
        widget.setRectangle(rect);
        widget.setPage(page);

        // set green border and yellow background
        // if you prefer defaults, just delete this code block
        final PDAppearanceCharacteristicsDictionary fieldAppearance
                = new PDAppearanceCharacteristicsDictionary(new COSDictionary());
        fieldAppearance.setBorderColour(new PDColor(new float[]{0,1,0}, PDDeviceRGB.INSTANCE));
        fieldAppearance.setBackground(new PDColor(new float[]{1,1,0}, PDDeviceRGB.INSTANCE));
        widget.setAppearanceCharacteristics(fieldAppearance);

        // make sure the widget annotation is visible on screen and paper
        widget.setPrinted(true);

        // Add the widget annotation to the page
        page.getAnnotations().add(widget);

        // set the field value
        textBox.setValue("Sample field");

        document.save(path);
    }
}
//copied from pdfbox examples
public static void processFields(final List<PDField> fields, final PDResources resources) {
fields.stream().forEach(f -> {
    f.setReadOnly(true);
    final COSDictionary cosObject = f.getCOSObject();
    final String value = cosObject.getString(COSName.DV) == null ?
                   cosObject.getString(COSName.V) : cosObject.getString(COSName.DV);
    System.out.println("Setting " + f.getFullyQualifiedName() + ": " + value);
    try {
        f.setValue(value);
    } catch (final IOException e) {
        if (e.getMessage().matches("Could not find font: /.*")) {
            final String fontName = e.getMessage().replaceAll("^[^/]*/", "");
            System.out.println("Adding fallback font for: " + fontName);
            resources.put(COSName.getPDFName(fontName), PDType1Font.HELVETICA);
            try {
                f.setValue(value);
            } catch (final IOException e1) {
                e1.printStackTrace();
            }
        } else {
            e.printStackTrace();
        }
    }
    if (f instanceof PDNonTerminalField) {
        processFields(((PDNonTerminalField) f).getChildren(), resources);
    }
});

Я бы ожидал, что pdfs, сгенерированные document.save () и job.print (), будут выглядеть одинаково вЗритель, но они этого не делают.Если я возьму PDF.save (), сгенерированный pdf с отключенным только для чтения, я могу использовать PDF Viewer, такой как FoxitReader, чтобы заполнить форму и распечатать ее снова.Это производит правильный вывод.Использование версии job.print () приводит к исчезновению текста, содержащегося в поле (текст) формы.Кто-нибудь знает, почему это так?

Я использую PDFBox 2.0.13 (последний выпуск) и LibreOffice 6.1.4.2. Здесь являются ссылочными файлами, а здесь вы можете загрузить отладчик (файл jar, запускаемый с помощью java -jar).

...