利用apache-pdfbox库修改pdf文件模板,进行信息替换

java 复制代码
public String createSignFile(Long id) throws IOException {
        // 1.验证企业信息
        CompanyDO company = validateCompanyExists(id);
        // 2.验证签约状态
        if(company.getSignStatus()!=0){
            throw exception(COMPANY_SIGN_STATUS_NOT_ZERO);
        }
        // 3.获取合同模板(合同模板有独立模板管理板块)
        String enterType = company.getEnterCompanyType()==1?"franchisee_enter":"service_provider_enter";
        AgreementRespDTO agreementDTO = operateAgreementApi.getAgreementByType(enterType);
        if(agreementDTO==null){
            throw exception(COMPANY_AGREEMENT_NOT_EXISTS);
        }
        String templatePath = agreementDTO.getFile();
        // 4.设定合同参数
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy年MM月dd日");
        String currentDate = sdf.format(new Date());

        Map<String, String> data = new HashMap<>();
        data.put("companyName", company.getName());
        data.put("secrecyInfo", "无");
        data.put("yearLimit", "一");
        data.put("StartDate", currentDate);
        // 5.生成合同文件
        // 5.1加载 pdf 模板和字体库文件
        //适用于本地资源路径(本地用于调试,信息为e:/file.pdf)
//        FileInputStream fis = new FileInputStream(templatePath);
        // 采用网络资源路径(系统中采用oss对象存储,所以获取的是网络路径)
        URL url = new URL(templatePath);
        URLConnection connection = url.openConnection();
        InputStream fis = connection.getInputStream();
        // 字体文件【华文仿宋】,可以自己换字体库
        URL fontUrl = new URL("https://你自己的地址.oss-cn-beijing.aliyuncs.com/stfangso.ttf");
        URLConnection fontConnection = fontUrl.openConnection();
        InputStream fontFile = fontConnection.getInputStream();
        // 开始读取
        //============ pdf 文件读取处理 ===============
        PDDocument pdf = PDDocument.load(fis);
        Map<COSName, PDFont> oldfont = new HashMap<COSName, PDFont>();
        COSName fontName = null;
        PDType0Font targetfont= PDType0Font.load(pdf,fontFile);

        for (PDPage page : pdf.getPages()) {
            PDFStreamParser pdfsp = new PDFStreamParser(page);
            pdfsp.parse();
            List<Object> tokens = pdfsp.getTokens();
            for (int j = 0; j < tokens.size(); j++) {
                //创建一个object对象去接收标记
                Object next = tokens.get( j );
                //instanceof判断其左边对象是否为其右边类的实例
                if(next  instanceof COSName) {
                    fontName= (COSName)next;
                    if(!oldfont.containsKey(fontName)) {
                        oldfont.put(fontName, page.getResources().getFont(fontName));
                    }
                }else
                if(next  instanceof COSString) {
                    COSString previous = (COSString)next;
                    try(InputStream in = new ByteArrayInputStream(previous.getBytes())){
                        StringBuffer sb = new StringBuffer();
                        while (in.available()>0) {
                            int rc = oldfont.get(fontName).readCode(in);
                            sb.append(oldfont.get(fontName).toUnicode(rc));
                        }
                        //重置COSString对象
                        previous.setValue(targetfont.encode(sb.toString()));
                    }
                }else if(next  instanceof COSArray) {
                    //PDF中的字符串
                    byte[] pstring = {};
                    int prej = 0;
                    COSArray previous  =(COSArray)next;
//                    //循环previous
                    for (int k = 0; k < previous.size(); k++) {
                        Object arrElement = previous.getObject( k );
                        if( arrElement instanceof COSString ){
                            //COSString对象>>创建java字符串的一个新的文本字符串。
                            COSString cosString =(COSString)arrElement;
                            //将此字符串的内容作为PDF文本字符串返回。
                            if (j == prej) {
                                byte[] thisbyte = cosString.getBytes();
                                byte[] temp = new byte[pstring.length+thisbyte.length];
                                System.arraycopy(pstring, 0, temp, 0, pstring.length);
                                System.arraycopy(thisbyte, 0, temp, pstring.length, thisbyte.length);
                                pstring=temp;
                            } else {
                                prej = j;
                                pstring = cosString.getBytes();
                            }
                        }
                    }
                    try(InputStream in = new ByteArrayInputStream(pstring)){
                        StringBuffer sb = new StringBuffer();
                        while (in.available()>0) {
                            int rc = oldfont.get(fontName).readCode(in);
                            sb.append(oldfont.get(fontName).toUnicode(rc));
                        }
                        String str =sb.toString();
                        for (Map.Entry<String, String> entry : data.entrySet()) {
                            String key = "${" + entry.getKey() + "}";
                            if (str.contains(key)) {
                                str = str.replace(key, entry.getValue() != null ? entry.getValue() : "");
                                break;
                            }
                        }
                        COSString cosString2 = (COSString) previous.getObject(0);
                        cosString2.setValue(targetfont.encode(str));
                    }
                    int total = previous.size()-1;
                    for (int k = total; k > 0; k--) {
                        previous.remove(k);
                    }
                }
            }
            PDStream updatedStream = new PDStream(pdf);
            OutputStream out = updatedStream.createOutputStream();
            ContentStreamWriter tokenWriter = new ContentStreamWriter(out);
            tokenWriter.writeTokens(tokens);
            out.close();
            oldfont.forEach((k,v)->{
                page.getResources().put(k, targetfont);
            });
            page.setContents(updatedStream);
        }
        //保存到本地中(主要用于调试)
        //pdf.save("d:/1.pdf");
        //pdf.close();
        //将文件直接保存上传(由于生成后,前台展示所以要直接上传获取上传地址进行前台回显)
        ByteArrayOutputStream out = new ByteArrayOutputStream();
        pdf.save(out);
        pdf.close();//记得关闭资源哦
        // 将输出流的内容转换为Base64编码的字符串
        byte[] bytes = out.toByteArray();

        String pdfUrl =fileApi.createFile(bytes);
        // 将上传后的文件,存到数据库中
        companyMapper.updateById(new CompanyDO().setId(id).setSignFileUrl(pdfUrl));

        return pdfUrl;
    }

该板块主要用于利用模板生成入驻企业的合同信息,便于在线发起合同签署功能。

采用了模板的变量替换方式,需要将变量信息预先插入到模板的指定位置。

相关推荐
穆友航11 小时前
PDF内容提取,MinerU使用
数据分析·pdf
拾荒的小海螺1 天前
JAVA:探索 PDF 文字提取的技术指南
java·开发语言·pdf
村东头老张1 天前
Java 实现PDF添加水印
java·开发语言·pdf
好美啊啊啊啊!2 天前
Thymeleaf模板引擎生成的html字符串转换成pdf
pdf·html
zhentiya2 天前
曼昆《经济学原理》第八版课后答案及英文版PDF
大数据·pdf
三天不学习2 天前
如何解决pdf.js跨域从url动态加载pdf文档
javascript·pdf
吾店云建站2 天前
9个最佳WordPress PDF插件(查看器、嵌入和下载)
程序人生·pdf·创业创新·流量运营·程序员创富·教育电商
007php0072 天前
基于企业微信客户端设计一个文件下载与预览系统
开发语言·python·docker·golang·pdf·php·企业微信
慧都小妮子2 天前
Spire.PDF for .NET【页面设置】演示:更改 PDF 页面大小
前端·pdf·.net