All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.netgrif.application.engine.pdf.service.PdfUtils.groovy Maven / Gradle / Ivy

Go to download

System provides workflow management functions including user, role and data management.

There is a newer version: 6.3.3
Show newest version
package com.netgrif.application.engine.pdf.service

import org.apache.pdfbox.cos.COSName
import org.apache.pdfbox.io.MemoryUsageSetting
import org.apache.pdfbox.multipdf.PDFMergerUtility
import org.apache.pdfbox.pdmodel.*
import org.apache.pdfbox.pdmodel.common.PDRectangle
import org.apache.pdfbox.pdmodel.encryption.AccessPermission
import org.apache.pdfbox.pdmodel.encryption.StandardProtectionPolicy
import org.apache.pdfbox.pdmodel.font.PDType0Font
import org.apache.pdfbox.pdmodel.interactive.form.PDAcroForm
import org.apache.pdfbox.pdmodel.interactive.form.PDField
import org.apache.pdfbox.pdmodel.interactive.form.PDNonTerminalField
import org.slf4j.Logger
import org.slf4j.LoggerFactory

class PdfUtils {

    private static final Logger log = LoggerFactory.getLogger(PdfUtils.class)

    static final int KEY_LENGTH = 128

    /**
     * Creates and returns new PDF file, created by shrinking input PDF file. To enlarge pdf, provide negative values.
     * @param inputFile input pdf
     * @param outputFileName output pdf file name
     * @param left left space in mm
     * @param right right space in mm
     * @param up upper space in mm
     * @param down lower space in mm
     * @return resized PDF file
     */
    static File resize(File inputFile, String outputFileName, float left, float right, float up, float down) {
        File outputFile = new File(outputFileName)
        PDDocument inputDoc = PDDocument.load(inputFile)
        PDDocument outputDoc = new PDDocument()

        PDPageTree pages = inputDoc.getDocumentCatalog().getPages()
        for (PDPage page : pages) {
            PDRectangle rectangle = new PDRectangle()
            rectangle.setLowerLeftX(-mmToPoint(left))
            rectangle.setLowerLeftY(-mmToPoint(down))
            rectangle.setUpperRightX(PDRectangle.A4.width + mmToPoint(right) as float)
            rectangle.setUpperRightY(PDRectangle.A4.height + mmToPoint(up) as float)
            page.setMediaBox(rectangle)
            page.setCropBox(rectangle)
            outputDoc.addPage(page)
        }
        outputDoc.save(outputFile)
        inputDoc.close()
        outputDoc.close()

        return outputFile
    }

    static float mmToPoint(float mm) {
        return (mm * 72) / 25.4F
    }

    static File removePages(File pdfFile, int ... pages) {
        PDDocument document = PDDocument.load(pdfFile)

        pages.each {
            document.removePage(it)
        }
        document.save(pdfFile)
        document.close()

        return pdfFile
    }

    static File encryptPdfFile(String outPdfPath, File input, String ownerPassword = "", String userPassword = "") {
        PDDocument doc = PDDocument.load(input)
        AccessPermission ap = new AccessPermission(canFillInForm: false, canModify: false)
        StandardProtectionPolicy spp = new StandardProtectionPolicy(ownerPassword, userPassword, ap)
        File encrypted = new File(outPdfPath)

        spp.setEncryptionKeyLength(KEY_LENGTH)
        doc.protect(spp)
        doc.save(encrypted)
        doc.close()

        return encrypted
    }

    static File mergePdfFiles(String outPdfName, File... files) {
        PDFMergerUtility pdfMerger = new PDFMergerUtility()
        pdfMerger.setDestinationFileName(outPdfName)

        files.each {
            pdfMerger.addSource(it)
        }

        pdfMerger.mergeDocuments(MemoryUsageSetting.setupMixed(100_000_000L, 500_000_000L))

        return new File(pdfMerger.getDestinationFileName())
    }

    static File fillPdfForm(String outPdfName, InputStream pdfFile, InputStream xmlFile) throws IllegalArgumentException {
        fillPdfForm(outPdfName, pdfFile, xmlFile.getText())
        xmlFile.close()
    }

    static File fillPdfForm(String outPdfName, InputStream pdfFile, String xml) throws IllegalArgumentException {
        try {
            PDDocument document = PDDocument.load(pdfFile)
            PDDocumentCatalog docCatalog = document.getDocumentCatalog()
            PDAcroForm acroForm = docCatalog.getAcroForm()

            addFieldValues(acroForm, xml, [:])
            return saveToFile(document, outPdfName)
        } catch (IOException e) {
            log.error("Filling PDF form failed: ", e)
            throw new IllegalArgumentException(e)
        } finally {
            pdfFile.close()
        }
    }

    static String addFont(PDDocument document, PDAcroForm acroForm, String fontPath) {
        PDResources res = acroForm.getDefaultResources()
        if (res == null)
            res = new PDResources()

//        File fontFile = ResourceFileLoader.loadResourceFile(fontPath)
        File fontFile = new File(fontPath)
        PDType0Font font = PDType0Font.load(document, new FileInputStream(fontFile), true)

        String fontName = res.add(font).name
        if (fontName == null)
            log.error("Could not add font to pdf resource")

        acroForm.setDefaultResources(res)

        return fontName
    }

    static void addFieldValues(PDAcroForm acroForm, String xmlText, Map fonts) {
        def fieldValues = new XmlSlurper().parseText(xmlText)

        fieldValues.children().each {
            setFieldValueAndFont(acroForm, it, fonts)
        }

        acroForm.flatten()
    }

    static setFieldValueAndFont(PDAcroForm acroForm, def xmlNode, Map fonts) {
        def id = ((xmlNode["@xfdf:original"] as String) ?: xmlNode.name()) as String
        def field = acroForm.fieldIterator.find { it.partialName.equalsIgnoreCase(id) }
        if (field == null) {
            log.warn("Cannot find field [$id]")
            return
        }

        try {
            String DA = field.getCOSObject().getString(COSName.DA)

            fonts.each { font ->
                if (DA.contains(font.key))
                    field.getCOSObject().setString(COSName.DA, DA.replaceAll(font.key, "/${font.value}"))
            }
            field.setValue(xmlNode as String)
        } catch (NullPointerException e) {
            log.warn("Cannot find field $id", e)
        }
    }

    static File saveToFile(PDDocument document, String outPdfName) {
        File file = new File(outPdfName)
        document.save(file)
        document.close()
        return file
    }

    static Map readPdfForm(InputStream inputStream) {

        Map result = new HashMap<>()

        PDDocument document = PDDocument.load(inputStream)
        PDDocumentCatalog docCatalog = document.getDocumentCatalog()
        PDAcroForm acroForm = docCatalog.getAcroForm()

        List fields = acroForm.getFields()

        fields.forEach({
            addAllFieldsAndChildFields(it, result)
        })
        document.close()
        inputStream.close()

        return result
    }

    static addAllFieldsAndChildFields(PDField field, Map result) {

        if (field instanceof PDNonTerminalField) {
            PDNonTerminalField nonTerminalField = (PDNonTerminalField) field
            nonTerminalField.getChildren().forEach({
                //Non terminal fields are not written to map at the moment
                //If needed, add it here
                addAllFieldsAndChildFields(it, result)
            })
        } else {
            result.put(field.getFullyQualifiedName(), field.getValueAsString())
        }
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy