利用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;
    }

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

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

相关推荐
一个处女座的程序猿5 小时前
LLMs之PDF:zeroX(一款PDF到Markdown 的视觉模型转换工具)的简介、安装和使用方法、案例应用之详细攻略
pdf·markdown·zerox
Dxy12393102166 小时前
python下载pdf
数据库·python·pdf
周亚鑫6 小时前
vue3 pdf base64转成文件流打开
前端·javascript·pdf
一名技术极客7 小时前
Vue2 doc、excel、pdf、ppt、txt、图片以及视频等在线预览
pdf·powerpoint·excel·文件在线预览
S. Dylan21 小时前
Edge浏览器打开PDF无法显示电子签章
edge·pdf
一马平川的大草原21 小时前
如何基于pdf2image实现pdf批量转换为图片
计算机视觉·pdf·文件拆分
m0_5945263021 小时前
Python批量合并多个PDF
java·python·pdf
hairenjing112321 小时前
将图片添加到 PDF 的 5 种方法
pdf
✿゚卡笨卡21 小时前
pdf 添加页眉页脚,获取前五页
java·pdf
blegn21 小时前
PDF编辑工具Adobe Acrobat DC 2023安装教程(附安装包)
pdf·办公软件·office