Java implementation PDF dynamic insert picture check box

Posted by marketboy on Sat, 19 Feb 2022 10:05:28 +0100

(1) Requirement description

Build PDF template and realize dynamic insertion of some data. It is mainly divided into three components: ordinary text, check box, QR code and dynamic insertion of pictures

(2) Make template

Because the commonly used software of pdf doesn't support editing, we first use WPS to edit in the form of Word to make the same style as the customer's needs, and then save it directly as The form of pdf is shown in the figure below:


After building the PDF, we need to use Adobe Acrobat DC software to edit the text field. The software download is not repeated

Open the test PDF with Adobe Acrobat DC, click the preparation form, and the following describes the basic use of the software. The value field at No. 1 is the built value field, which can be customized, dragged and modified. Some customized components can be added to No. 2, such as text, radio box, button, etc. No. 3 shows the domain object of the current PDF

Configure the data source domain name, which is the property of dynamic insertion value matching later. The text component can be directly used for image insertion, as long as the domain name matches

The check box is explained separately. During the development, I found that there are many statements On the network. In fact, the selection of the check box is not clear. Specifically, it is OK to set On, Yes, Yes or other, and the default value of PDF is also different. This needs to be specially edited by Adobe Acrobat DC, and the style can be set in the option, The exported value is the On you selected in the code later. When you set On to the corresponding field value, it means to confirm the selection. This needs special attention, otherwise there is a problem that cannot be selected and no solution can be found

(3) Code development

Import dependency, itextpdf is the main editing dependency, and iText Asian is the dependency of Asian fonts

    <dependency>
            <groupId>com.itextpdf</groupId>
            <artifactId>itextpdf</artifactId>
            <version>5.5.13</version>
        </dependency>

        <dependency>
            <groupId>com.itextpdf</groupId>
            <artifactId>itext-asian</artifactId>
            <version>5.2.0</version>
        </dependency>

PDF operation code

 public static byte[] createSimplePdf(Map<String, Map<String, String>> dataMap, String templatePath) {
        PdfReader reader;
        ByteArrayOutputStream bos;
        PdfStamper stamper;
        ByteArrayOutputStream out = null;
        try {
            //Get file stream
            reader = new PdfReader(templatePath);
            bos = new ByteArrayOutputStream();
            stamper = new PdfStamper(reader, bos);
            AcroFields form = stamper.getAcroFields();
            //Traversal setting
            for (Map.Entry<String, Map<String, String>> data : dataMap.entrySet()) {
                String fieldType = data.getKey();
                if ("simple".equals(fieldType)) {
                    for (Map.Entry<String, String> dataValue : data.getValue().entrySet()) {
                        //Support Chinese
                        BaseFont bfChinese = BaseFont.createFont("STSong-Light", "UniGB-UCS2-H", BaseFont.NOT_EMBEDDED);
                        form.setFieldProperty(data.getKey(), "textfont", bfChinese, null);
                        //saveAppearance needs to be set to true,
                        form.setField(dataValue.getKey(), dataValue.getValue(), true);
                    }
                } else if ("image".equals(fieldType)) {
                    //Processing picture type fields
                    for (Map.Entry<String, String> dataValue : data.getValue().entrySet()) {
                        int pageNo = form.getFieldPositions(dataValue.getKey()).get(0).page;
                        Rectangle signRect = form.getFieldPositions(dataValue.getKey()).get(0).position;
                        float x = signRect.getLeft();
                        float y = signRect.getBottom();
                        // Read pictures
                        Image image = PngImage.getImage(dataValue.getValue());
                        // Get the page of the operation
                        PdfContentByte under = stamper.getOverContent(pageNo);
                        // Scale the picture according to the size of the field
                        image.scaleToFit(signRect.getWidth(), signRect.getHeight());
                        // Add picture
                        image.setAbsolutePosition(x, y);
                        under.addImage(image);
                        stamper.setFormFlattening(true);
                    }

                }
            }
            //Non editable
            stamper.setFormFlattening(true);
            out = new ByteArrayOutputStream();
            Document doc = new Document();
            PdfCopy copy = new PdfCopy(doc, out);
            stamper.close();
            doc.open();
            PdfImportedPage importPage = copy.getImportedPage(new PdfReader(bos.toByteArray()), 1);
            copy.addPage(importPage);
            doc.close();
            out.close();
        } catch (IOException | DocumentException e) {
            e.printStackTrace();
        }
        assert out != null;
        return out.toByteArray();
    }

Test code

    public static void main(String[] args) throws IOException {
        Map<String, Map<String, String>> dataSet = new HashMap<>(3);
        String imgPath = "D:\\img.png";
        Map<String, String> map1 = new HashMap<>(2);
        map1.put("name", "Hello World");
        map1.put("flag", "On");
        Map<String, String> map2 = new HashMap<>(2);
        map2.put("img", imgPath);
        dataSet.put("simple", map1);
        dataSet.put("image", map2);
        byte[] simplePdf = PdfUtil.createSimplePdf(dataSet, "D:\\test.pdf");
        File file = new File("target.pdf");
        FileOutputStream fileOutputStream = new FileOutputStream(file);
        fileOutputStream.write(simplePdf);
        fileOutputStream.close();

    }

Generated PDF results

explain:
1: In order to facilitate the operation of Map directly, it is recommended to replace the actual development with entity class
2: At present, only text, check box and picture types are encountered. The operation of text check box is the same, and the picture is slightly different
3: The saveAppearance must be set to true during check box operation, otherwise it will not take effect

Topics: Java pdf