admin管理员组

文章数量:1592412

文章目录

      • (一)需求描述
      • (二)制作模板
      • (三)代码开发

(一)需求描述

构建PDF模板,对其中部分数据实现动态插入,主要分为三个组件:普通文本,复选框,二维码图片的动态插入

(二)制作模板

因为PDF常用的软件不让支持编辑,我们就先使用WPS以Word的形式进行编辑制作出与客户需求一样的样式,然后直接另存为 .pdf 的形式如下图所示:


构建完PDF之后,我们需要使用Adobe Acrobat DC的软件来编辑文本域,软件下载不在赘述

用Adobe Acrobat DC打开该测试PDF,点击准备表单,下面介绍下该软件的基本使用,其中序号1处为构建的值域,可以自定义拖曳修改,序号2可以添加一些自定义的组件,比如文本,单选框,按钮等等,序号3展示当前PDF的域对象

配置数据源域名称,这个就是后面动态插入值匹配的属性,图片插入可以直接使用文本组件,只要域名匹配即可

复选框单独说明一下,我在开发中发现网络上存在多种说法对于复选框的选择,其实这个都是不明确的,具体是设置On,是,Yes或者其他的都是可以的,而且PDF的默认值也不一样,这个需要在Adobe Acrobat DC特别编辑下,在选项中可以设置样式,其中导出值就是后面你在代码里选择的On,当给对应域值设置On即表示确认选择,这个需要特别注意下,不然出现无法选择问题找不到解决办法

(三)代码开发

导入依赖,itextpdf是主要的编辑PDF依赖,itext-asian是亚洲字体的依赖

    <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操作代码

 public static byte[] createSimplePdf(Map<String, Map<String, String>> dataMap, String templatePath) {
        PdfReader reader;
        ByteArrayOutputStream bos;
        PdfStamper stamper;
        ByteArrayOutputStream out = null;
        try {
            //获取文件流
            reader = new PdfReader(templatePath);
            bos = new ByteArrayOutputStream();
            stamper = new PdfStamper(reader, bos);
            AcroFields form = stamper.getAcroFields();
            //遍历设值
            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()) {
                        //支持中文
                        BaseFont bfChinese = BaseFont.createFont("STSong-Light", "UniGB-UCS2-H", BaseFont.NOT_EMBEDDED);
                        form.setFieldProperty(data.getKey(), "textfont", bfChinese, null);
                        //saveAppearance需要设置为true,
                        form.setField(dataValue.getKey(), dataValue.getValue(), true);
                    }
                } else if ("image".equals(fieldType)) {
                    //处理图片类型域
                    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();
                        // 读图片
                        Image image = PngImage.getImage(dataValue.getValue());
                        // 获取操作的页面
                        PdfContentByte under = stamper.getOverContent(pageNo);
                        // 根据域的大小缩放图片
                        image.scaleToFit(signRect.getWidth(), signRect.getHeight());
                        // 添加图片
                        image.setAbsolutePosition(x, y);
                        under.addImage(image);
                        stamper.setFormFlattening(true);
                    }

                }
            }
            //不可编辑
            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();
    }

测试代码

    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();

    }

生成的PDF结果

说明:
1:上面为了方便直接用了Map操作的,建议实际开发替换为实体类代替
2:目前只碰到了文本、复选框,图片类型,其中文本复选框操作一样,图片稍有不同
3:复选框操作的时候必须设置saveAppearance需要设置为true否则不会生效

本文标签: 复选框插入图片动态JavaPDF