springboot对已有pdf追加内容,itext我居然从来不知道......

【业务场景】

对已有的pdf追加签名,签名内容包含:当前审批等级、签名(图片)、审批意见、审批时间

【技术关键词】

  • pdf定位与合成,使用itext对已有pdf追加新内容;
  • itext可以将文字、表格、图片等合成pdf,以及对pdf每页进行处理

【大致操作流程】

  1. 获取PdfReader对象,该对象指名原始操作文件,通过.getNumberOfPages()方法,可以拿到总页数,为pdf设置当前页共几页的页脚
  2. 获取PdfStamper对象,该对象有两个参数,分别指向原始pdf新生成的pdf,相当于整个新的pdf文件,结束对整个pdf操作时,用.close()结束
  3. 获取PdfContentByte对象,这个对象拿到的是pdf操作的当前页,在所需操作的页面上添加内容。
    • 需要处理新一页pdf时,需要重新获取PdfContentByte对象。
    • 处理文字时,用.beginText()开始,.endText()结束,添加几行则需要使用几对
    • 图片和文字设置绝对位置,有两个参数,对应的含义是左边距底边距

废话不多说,直接上代码,走着~

【使用方式】

一、引入itext依赖
  		 <dependency>
            <groupId>com.itextpdf</groupId>
            <artifactId>itextpdf</artifactId>
            <version>5.5.10</version>
        </dependency>

        <dependency>
            <groupId>com.itextpdf</groupId>
            <artifactId>itext-asian</artifactId>
            <version>5.2.0</version>
        </dependency>
二、操作pdf
	@Override
    public CommonResponse pdf(String fileName) throws BizException{
        CommonResponse rsp = new CommonResponse();
        InputStream testPdf;
        String pathUrl = "";
        ByteArrayInputStream inputStream = null;
        try {
            // 从ftp下载文件
            testPdf= ftpUtil.download(fileName);
        } catch (IOException e) {
            throw new BizException(SysRetCodeConstants.SYSTEM_ERROR.getCode(), "下载pdf失败!");
        }
        if (null == tzPdf) {
            throw new BizException(SysRetCodeConstants.SYSTEM_ERROR.getCode(), "下载pdf失败!");
        }
        ByteArrayOutputStream outputStream = null;
        try {
            // 获取pdf对象,参数是pdf流,PdfReader有几个构造函数供选择
            PdfReader pdfReader = new PdfReader(tzPdf);
            // 设置输出流,一般不输出到本地,这里直接把生成的流上传到ftp服务器
            outputStream = new ByteArrayOutputStream();
            // 获得pdf修改器,构造函数分别是原始pdf输入流,生成的pdf输出流
            PdfStamper pdfStamper = new PdfStamper(pdfReader, outputStream);
            // 解析中文。不加这行添加的中文不能显示;
            BaseFont bf = BaseFont.createFont("STSong-Light", "UniGB-UCS2-H", BaseFont.NOT_EMBEDDED);
            // 对每页处理
            for (int i = 1; i <= pdfReader.getNumberOfPages(); i++) {
                // 从第二页开始,每页pdf都要添加图片,文字
                if (i == 2) {
                    // 获取审批流程
                    List<CheckNodeAndSignOut> checkNodeAndSigns = getCheckNodesById();
                    // 遍历每一级结点处理:设置图片、文字的位置
                    for (int j = 0; j < checkNodeAndSigns.size(); j++) {
                        // 获取pdf每页操作对象。
                        // 注意:PdfStamper获取PdfContentByte 操作对象有两种方式.getOverContent(i)和.getUnderContent(i),前者覆盖原有pdf内容,后者被原有内容覆盖
                        PdfContentByte cd = pdfStamper.getOverContent(i);
                        // 1. 添加图片
                        if (StringUtils.isNotBlank(checkNodeAndSigns.get(j).getUrl())) {
                            Image image = Image.getInstance(checkNodeAndSigns.get(j).getUrl());
                            // 等比例缩小15%
                            image.scalePercent(15);
                            // 设置绝对位置
                            image.setAbsolutePosition(80 + (j * 125), 60);
                            cd.addImage(image);
                        }
                        // 2. 添加文本1
                        cd.beginText();
                        // 设置文本绝对坐标(左边距,底边距)
                        cd.setTextMatrix(50 + (j * 130), 70);
                        // 字体属性
                        cd.setFontAndSize(bf, 10);
                        // 设置文本内容
                        cd.showText(checkNodeAndSigns.get(j).getOaName() + ":");
                        // 结束加载文本
                        cd.endText();
                        // 2. 添加文本2
                        cd.beginText();
                        cd.setTextMatrix(50 + (j * 140), 50);
                        cd.setFontAndSize(bf, 10);
                        //设置文本
                        cd.showText(StringUtils.isNotBlank(checkNodeAndSigns.get(j).getOaDetail()) ? checkNodeAndSigns.get(j).getOaDetail() : "");
                        //结束加载文本
                        cd.endText();
                    }
                }
                PdfContentByte cd = pdfStamper.getUnderContent(i);
                //加载文本
                cd.beginText();
                Rectangle size = pdfReader.getPageSize(1);
                // 宽度
                float pdfX = size.getRight();
                //设置文本绝对坐标
                cd.setTextMatrix(pdfX / 2 - 5, 10);
                cd.setFontAndSize(bf, 8);
                //设置文本
                cd.showText("第" + i + "页,共" + pdfReader.getNumberOfPages() + "页");
                //结束加载文本
                cd.endText();
            }
            pdfStamper.close();
            // 上传到ftp
            inputStream = new ByteArrayInputStream(outputStream.toByteArray());
            String pdfName = UUID.randomUUID() + ".pdf";
            boolean result = ftpUtil.uploadFileToFtp("test", pdfName, inputStream);
            if (result) {
                String filePath = ConfigValues.get("filePath"); //从配置文件中获取文件地址
                String pdfDir = ConfigValues.get("pdfDir"); //获取文件目录
                pathUrl = filePath + pdfDir + pdfName;
                log.info(">>>>>>>>>>>>>>>>>pdf上传的地址:{}>>>>>>>>>>>>>>>>>>>>>>", pathUrl);
            }
        } catch (Exception e) {
            log.error("操作pdf失败:{}", e.getMessage());
            throw new BizException(SysRetCodeConstants.SYSTEM_ERROR.getCode(), "操作失败!");
        } finally {
            try {
                if (outputStream != null) {
                    outputStream.flush();
                    outputStream.close();
                }
                if (tzPdf != null) {
                    tzPdf.close();
                }
                if (inputStream!=null){
                    inputStream.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        rsp.setCode(SysRetCodeConstants.SUCCESS.getCode());
        rsp.setMsg(pathUrl);
        return rsp;
    }

这是一个有情怀的程序媛,欢迎来到我的世界

分享我的喜怒哀乐,我们一起成长,一起变的更好!

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值