itext 填充PDF表单

需要工具

  1. 处理pdf的两个itext 的jar包,其中一个是处理汉字兼容问题
  2. 需要使用软件 Acrobat Pro 制作表单

使用itext填充表单制作pdf,需要 itext 的jar包,itextpdf 开始使用的是 5.5.13 但存在bug,后面降到使用5.5.3解决问题,具体见“遇到的坑”。


                com.itextpdf
                itextpdf
                5.5.3
            
            
                com.itextpdf
                itext-asian
                5.2.0
            

制作pdf表单

需要使用软件 Acrobat Pro 制作表单,文字的大小和格式也可以使用该软件设置
itext 填充PDF表单_第1张图片

填充表单代码

表单内容包括文本和图片

填充表单代码和插入图片(比如签名)

public static void commonFillPdfForm(Map formMap, String templatePath, String outputFilePath,
                                         String signatureString) {
        //生成的新文件路径
        PdfReader reader;
        FileOutputStream out;
        ByteArrayOutputStream bos;
        PdfStamper stamper;
        Document doc = new Document();
        try {
            createDirectory(outputFilePath);
            //输出流
            out = new FileOutputStream(outputFilePath);
            //读取pdf模板
            reader = new PdfReader(templatePath);
            bos = new ByteArrayOutputStream();
            stamper = new PdfStamper(reader, bos);
            AcroFields form = stamper.getAcroFields();

            form.addSubstitutionFont(BaseFont.createFont("STSong-Light", "UniGB-UCS2-H", BaseFont.NOT_EMBEDDED));

            java.util.Iterator it = form.getFields().keySet().iterator();
            while (it.hasNext()) {
                String name = it.next().toString();
                if(StringUtils.isBlank(formMap.get(name))){
                    continue;
                }
                form.setField(name, formMap.get(name));

                //处理 checkbox
                int type = form.getFieldType(name);
                System.out.println("key:" + name + ", type:" + type);
                if(type == 2){
                    //注意版本问题,这个true必填,否则会变成x; 或者使用较低版本
                    //form.setField(name, "On", true);
                    //form.setField(name, formMap.get(name), true);
                    form.setField(name, formMap.get(name));
                }
            }

            //处理签名
            if (StringUtils.isNotBlank(signatureString)) {
                // 通过域名获取所在页和坐标,左下角为起点
                int pageNo = form.getFieldPositions("sign").get(0).page;
                Rectangle signRect = form.getFieldPositions("sign").get(0).position;
       
                // 读图片
                BASE64Decoder decoder = new BASE64Decoder();
                Image image = Image.getInstance(decoder.decodeBuffer(signatureString));
                // 获取操作的页面
                PdfContentByte under = stamper.getOverContent(pageNo);
                // 根据域的大小缩放图片
                image.scaleToFit(signRect.getWidth(), signRect.getHeight());
                // 添加图片
                image.setAbsolutePosition(signRect.getLeft(), signRect.getBottom());
             
                under.addImage(image);
            }
            //如果为false那么生成的PDF文件还能编辑,一定要设为true
            stamper.setFormFlattening(true);
            stamper.close();

            PdfCopy copy = new PdfCopy(doc, out);
            doc.open();
            PdfImportedPage importPage;
            for(int i = 1; i <= reader.getNumberOfPages(); i++) {
                importPage = copy
                    .getImportedPage(new PdfReader(bos.toByteArray()), i);
                copy.addPage(importPage);
            }
            doc.close();
        } catch (Exception e) {
            logger.error("error",e);
        }
    }

pdf内容勾选

itext 填充PDF表单_第2张图片

上面代码中表单处理打勾场景

fields.setField(key, “On”, true); 

遇到的坑

  1. 中文乱码
    通过使用 text-asian 包解决中文问题,但发现仍不好使,怀疑是 Acrobat Pro 版本的问题,于是下载了一个新版本解决中文乱码。
  2. itextpdf 包的bug
    当时为了实现打勾的功能出现问题:勾形变成了打叉。查了下是版本问题,于是将itext的版本降到 5.5.3解决,参考:https://ithelp.ithome.com.tw/articles/10193321
方式一:(该方式对我没起作用)
fields.SetField(item.Key, item.Value, true);

方式二:降低版本
5.5.4 以前的版本都正常,
5.5.5 開始出現此問題,但此版本沒有 saveAppearance 參數可以解決此問題,
5.5.7 之後才有 saveAppearance 參數,
所以除了 5.5.5 和 5.5.6 之外的版本都可以使用此方法解決此問題。

参考资料

Itext填写pdf中的复选框对勾问题解决

你可能感兴趣的:(Java,Tool)