近况

好长时间没有写博客了,前几个月都在准备软考,白天上班敲代码,晚上回家学软考,确实有点累啊
没有太多时间专门去学习,当然也是我太懒了,我从写博客中得到的快乐越来越少了,因为我想要的更清楚了
唯一让我坚持下去的可能是,单纯当做笔记记录一下,以免以后忘记又要重新找资料学习。
之后我大概会写一些类库的使用,网上一大堆类似的博客,我收集一些写的不错的博客贴上来,
另外我也自己尝试使用一下这些类库,文章最末尾的链接就是一些测试代码

市面上PDF类库介绍

目前行业内有很多类库可以使得Java去操作PDF,例如PDFBox,iText5,iText7,OpenPDF
这些类库区别如下:

1. PDFBox的功能相对较弱,iText5和iText7的功能非常强悍;
2. iText5的资料网上相对较多,如果出现问题容易找到解决方案;PDFBox和iText7的网上资料相对较少,如果出现问题不易找到相关解决方案;
3. 通过阅读PDFBox代码目前PDFBox还没提供自定义签章的相关接口;iText5和iText7提供了处理自定义签章的相关实现
4. PDFBox只能实现把签章图片加签到PDF文件;iText5和iText7除了可以把签章图片加签到PDF文件,还可以实现直接对签章进行绘制,把文件绘制到签章上。
5. PDFBox和iText5/iText7使用的协议不一样。PDFBox免费使用,AGPL商用收费
6. OpenPDF是基于itext4开发的开源的jar,itext5也是基于itext4开发,itext5是部分开源,部分收费,且官方不再更新维护,需要引入的包多,itext7绝大部分功能收费了

Maven依赖

导入iText7依赖
<dependency>
  <groupId>com.itextpdf</groupId>
  <artifactId>itext7-core</artifactId>
  <version>7.1.7</version>
  <type>pom</type>
</dependency>

导入iText5依赖
<dependency>
  <groupId>com.itextpdf</groupId>
  <artifactId>itextpdf</artifactId>
  <version>5.5.10</version>
</dependency>
<dependency>
  <groupId>com.itextpdf.tool</groupId>
  <artifactId>xmlworker</artifactId>
  <version>5.5.10</version>
</dependency>
<!--中文支持-->
<dependency>
  <groupId>com.itextpdf</groupId>
  <artifactId>itext-asian</artifactId>
  <version>5.2.0</version>
</dependency>

导入pdfbox依赖,pdfbox也需要导入iText5的依赖
<dependency>
  <groupId>org.apache.pdfbox</groupId>
  <artifactId>pdfbox</artifactId>
  <version>2.0.24</version>
</dependency>

iText库中常用类

PDFBox的使用

使用pdfBox填充PDF模板是个不错的方式

  • 1.制作PDF模板,使用Acrobat DC软件制作,下面是阿里云盘的资源

    Adobe Acrobat DC 2021 SP.exe
    https://www.aliyundrive.com/s/WBdUC3oCgh5
    点击链接保存,或者复制本段内容,打开「阿里云盘」APP ,无需下载极速在线查看,视频原画倍速播放。

    安装好软件后,搜索功能:表单工具或者准备表单,打开待制作的pdf,在需要填充数据的地方添加文本域
    设置变量名,之后代码中会根据文本域的变量名去填充数据,也可以对文本域设置一些样式。

  • 2.编写代码

    public class iText5 {
        public static void main(String[] args) {
            //往map中填充数据,键就是我们在生成模版的时候,里面的fieldName,value就是要填充的数据
            HashMap map = new HashMap<String, String>(30);
    
            //填充图片,传入的是一个图片的url地址,但实际上,是要传下图片的byte[]数据,
            // 在工具类中,会先获取图片的byte数据,然后,再往pdf里面填充,具体可以参照工具方法中的备注
            //map.put("signImage", "https://ls.resource.penrose.com.cn/");
    
            //模版PDF文件的地址
            String sourceFile = "C:\\Users\\Coco\\Desktop\\template2.pdf";
            //填充以后,生成的PDF文件
            String targetFile = "C:\\Users\\Coco\\Desktop\\testForm_fill2.pdf";
            //调用工具方法
            try {
                genPdf(map, sourceFile, targetFile);
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        
        /**
         * 生成PDF文件
         * @param map 要往模版中填充的数据
         * @param sourceFile 模版PDF文件的路径
         * @param targetFile 填充数据以后,生成的PDF的文件路径
         * @throws IOException
         */
        private static void genPdf(HashMap map, String sourceFile, String targetFile) throws IOException {
            File templateFile = new File(sourceFile);
            fillParam(map, FileUtils.readFileToByteArray(templateFile), targetFile);
        }
    
        /**
         * Description: 使用map中的参数填充pdf,map中的key和pdf表单中的field对应
         */
        public static void fillParam(Map<String, String> fieldValueMap, byte[] file, String contractFileName) {
            FileOutputStream fos = null;
            String TTF_PATH = "C:\\WINDOWS\\Fonts\\SimHei.ttf";
            try {
                fos = new FileOutputStream(contractFileName);
                PdfReader reader = null;
                PdfStamper stamper = null;
                BaseFont base;
                try {
                    reader = new PdfReader(file);
                    stamper = new PdfStamper(reader, fos);
                    stamper.setFormFlattening(true);
                    //获取字体文件,TTF_PATH表示字体文件的路径
                    base = BaseFont.createFont(TTF_PATH, BaseFont.IDENTITY_H, BaseFont.EMBEDDED);
                    //获取模板中待填充的字段并设置字体样式
                    AcroFields acroFields = stamper.getAcroFields();
                    /*for (Object key : acroFields.getFields().keySet()) {
                        //设置字体
                        acroFields.setFieldProperty((String) key, "textfont", base, null);
                        //设置字体大小
                        acroFields.setFieldProperty((String) key, "textsize", new Float(8), null);
                    }*/
                    if (fieldValueMap != null) {
                        for (String fieldName : fieldValueMap.keySet()) {
                            //填充其它文本数据
                            acroFields.setField(fieldName, fieldValueMap.get(fieldName));
                            //填充图片
                            /*if (fieldName.equals("signImage")) {
                                //这里先获取图片的byte数据
                                byte[] bytes = PDFUtil.getImage(fieldValueMap.get(fieldName));
                                if (bytes != null) {
                                    int pageNo = acroFields.getFieldPositions(fieldName).get(0).page;
                                    Rectangle signRect = acroFields.getFieldPositions(fieldName).get(0).position;
                                    float x = signRect.getLeft();
                                    float y = signRect.getBottom();
                                    // 读图片
                                    Image image = Image.getInstance(bytes);
                                    // 获取操作的页面
                                    PdfContentByte under = stamper.getOverContent(pageNo);
                                    // 根据域的大小缩放图片
                                    image.scaleToFit(signRect.getWidth(), signRect.getHeight());
                                    // 添加图片
                                    image.setAbsolutePosition(x, y);
                                    under.addImage(image);
                                    stamper.setFormFlattening(true);
                                }
                            } else {
    
                            }*/
                        }
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                } finally {
                    if (stamper != null) {
                        try {
                            stamper.close();
                        } catch (Exception e) {
                            e.printStackTrace();
                        }
                    }
                    if (reader != null) {
                        reader.close();
                    }
                }
    
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                IOUtils.closeQuietly(fos);
            }
        }
    }

文章推荐