溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

怎么用Java實現(xiàn)合同模板簽署的功能

發(fā)布時間:2021-06-15 09:58:35 來源:億速云 閱讀:757 作者:小新 欄目:web開發(fā)

這篇文章主要介紹怎么用Java實現(xiàn)合同模板簽署的功能,文中介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們一定要看完!

一、前言

事情是這個樣子的,小農(nóng)的公司,之前有個功能需要簽署來進行一系列的操作,于是我們引入了一個三方平臺的簽署——上上簽,但是有一個比較尷尬的點就是,它不支持合同在瀏覽器上和附件一起預覽的,我們想要的是需要將附件拼接在合同主文件中一起展示,但是它不支持,于是我們就開了一個需求會。。。

  • 產(chǎn)品說,我們要做一個線上合同簽署的功能,不依靠第三方來完成,可以瀏覽器上預覽和下載合同,小農(nóng),你這邊能做嗎?

我一聽,這個啊,這個有點難度啊(我需要時間),不太好做,之前我們接入的第三方就沒有完全完成瀏覽器預覽的功能,相當于我們做一個和這個第三方一模一樣的東西,而且還要比它那個兼容更多的功能,不太好做(確實有點不太好做),加上之前也沒有做過,心里沒有底。

  • 產(chǎn)品說,這個沒有辦法(你做也得做,不做也得做),是領導要求的(上面要求的,你只能做),你看下完成這些功能大概需要多久?

于是只能硬著頭皮上了,于是給了一個大概的時間后,就開始研究了,什么是快樂星球,如果你想知道的話,那我就帶你研究,what???等等,跑偏了,回來回來。

二、那我就帶你研究

研究什么?什么是快樂星球[手動狗頭],咳咳,洗腦了,請你立即停止你的傻*行為。

我們知道,如果是想要操作PDF的話(因為簽署合同一般都是用的PDF,同志們?yōu)槟銈兘庖闪?,掌聲可以響起來?,所以一般都是用  iText(PDF操作類庫),操作類庫??? ,咳咳,你怎么回事?

我們一般都是要使用 Adobe工具設計表單和iText  來進行內(nèi)容操作,這也是我們今天需要講解的主體,知道了用什么,我們來講一下我們的需求是什么?工作后的小伙伴有沒有覺得很可怕,“我們來講一下需求”,首先需要實現(xiàn)的是  通過PDF模板填充我們對應的甲乙方基本數(shù)據(jù)后,生成PDF文件,然后再將數(shù)據(jù)庫的特定數(shù)據(jù)拼接在PDF里面一起,通過甲乙方先后簽署后,然后讓該合同進行生效操作!可以預覽和下載。

要求就是這么個要求,聽著倒是不難,主要是之前沒有做過,心里不太有譜,但是做完之后,不得不呼自己真是個天才啊,我可真聰明,想起小農(nóng)從實習的時候就是做的PDF,如今工作這么久了還是在做PDF的,真是漂(cao)亮(dan),那就做唄,誰怕誰啊!

三、Adobe工具

工欲善其事必先利其器,首先如果想要填充PDF模板里面的內(nèi)容的話,我們需要使用到 AdobeAcrobatPeoDC這個工具

下載地址

鏈接:https://pan.baidu.com/s/1JdeKr7-abc4bajhVxoiYWg 提取碼:6h0i

1、打開PDF文件

當我們下載好 AdobeAcrobatPeoDC后,用它打開PDF文件,然后點擊 準備表單

怎么用Java實現(xiàn)合同模板簽署的功能

2、添加文本域

點擊添加文本域

怎么用Java實現(xiàn)合同模板簽署的功能

3、填寫變量名

這個變量名就是我們填充數(shù)據(jù)的參數(shù),要一一對應

怎么用Java實現(xiàn)合同模板簽署的功能

4、填寫完成后,如下所示

怎么用Java實現(xiàn)合同模板簽署的功能

5、開始安排

別擔心小伙伴們,項目都給你們準備好了項目地址:https://github.com/muxiaonong/other/tree/master/pdfsigndemo

jar文件:

<dependencies>         <dependency>             <groupId>org.springframework.boot</groupId>             <artifactId>spring-boot-starter-web</artifactId>         </dependency>          <dependency>             <groupId>org.springframework.boot</groupId>             <artifactId>spring-boot-starter-test</artifactId>             <scope>test</scope>         </dependency>         <dependency>             <groupId>com.itextpdf</groupId>             <artifactId>itextpdf</artifactId>             <version>5.5.5</version>         </dependency>         <dependency>             <groupId>com.itextpdf</groupId>             <artifactId>layout</artifactId>             <version>7.1.15</version>         </dependency>          <dependency>             <groupId>com.itextpdf</groupId>             <artifactId>itext-asian</artifactId>             <version>5.2.0</version>         </dependency>         <dependency>             <groupId>org.springframework</groupId>             <artifactId>spring-test</artifactId>         </dependency>          <!--itext生成word文檔,需要下面dependency-->         <dependency>             <groupId>com.lowagie</groupId>             <artifactId>iText-rtf</artifactId>             <version>2.1.4</version>         </dependency>         <dependency>             <groupId>commons-collections</groupId>             <artifactId>commons-collections</artifactId>             <version>3.2.2</version>         </dependency>         <dependency>             <groupId>org.projectlombok</groupId>             <artifactId>lombok</artifactId>             <optional>true</optional>         </dependency>     </dependencies>

根據(jù)PDF模板生成文件和拼接產(chǎn)品的數(shù)據(jù)

 /**      * 根據(jù)PDF模板生成PDF文件      * @return      */     @GetMapping("generatePdf")     public String generatePdf() throws Exception{ //        File file = ResourceUtils.getFile("classpath:"+SAVE_PATH);         File pdfFile = new File(ResourceUtils.getURL("classpath:").getPath()+SAVE_PATH);         try {             PdfReader pdfReader;             PdfStamper pdfStamper;             ByteArrayOutputStream baos;              Document document = new Document(); //              PdfSmartCopy pdfSmartCopy = new PdfSmartCopy(document,                     new FileOutputStream(pdfFile));              document.open();              File file = ResourceUtils.getFile("classpath:"+templatePath);             pdfReader = new PdfReader(file.getPath());             int n = pdfReader.getNumberOfPages();             log.info("頁數(shù):"+n);             baos = new ByteArrayOutputStream();             pdfStamper = new PdfStamper(pdfReader, baos);              for(int i = 1; i <= n; i++) {                 AcroFields acroFields = pdfStamper.getAcroFields();                  //key statement 1                 acroFields.setGenerateAppearances(true);                  //acroFields.setExtraMargin(5, 5);                 acroFields.setField("customerAddress", "上海市浦東新區(qū)田子路520弄1號樓");                 acroFields.setField("customerCompanyName", "上海百度有限公司");                 acroFields.setField("customerName", "張三");                 acroFields.setField("customerPhone", "15216667777");                 acroFields.setField("customerMail", "123456789@sian.com");                  acroFields.setField("vendorAddress", "上海市浦東新區(qū)瑟瑟發(fā)抖路182號");                 acroFields.setField("vendorCompanyName", "牧小農(nóng)科技技術有限公司");                 acroFields.setField("vendorName", "王五");                 acroFields.setField("vendorPhone", "15688886666");                 acroFields.setField("vendorMail", "123567@qq.com");                  acroFields.setField("effectiveStartTime", "2021年05月25");                 acroFields.setField("effectiveEndTime", "2022年05月25");                  //true代表生成的PDF文件不可編輯                 pdfStamper.setFormFlattening(true);                  pdfStamper.close();                  pdfReader = new PdfReader(baos.toByteArray());                   pdfSmartCopy.addPage(pdfSmartCopy.getImportedPage(pdfReader, i));                 pdfSmartCopy.freeReader(pdfReader);                 pdfReader.close();             }             pdfReader.close();             document.close();         } catch(DocumentException dex) {             dex.printStackTrace();         } catch(IOException ex) {             ex.printStackTrace();         }         //創(chuàng)建PDF文件         createPdf();           File file3 = new File(ResourceUtils.getURL("classpath:").getPath()+TEMP_PATH);         File file1 = new File(ResourceUtils.getURL("classpath:").getPath()+outputFileName);          List<File> files = new ArrayList<>();         files.add(pdfFile);         files.add(file3);          try {             PdfUtil pdfUtil = new PdfUtil();             pdfUtil.mergeFileToPDF(files,file1);         } catch (Exception e) {             e.printStackTrace();         }          //如果你是上傳文件服務器上,這里可以上傳文件 //        String url = fileServer.uploadPdf(File2byte(file1));          //刪除總文件         //如果是你本地預覽就不要刪除了,刪了就看不到了 //        if(file1.exists()){ //            file1.delete(); //        }         //刪除模板文件         if(pdfFile.exists()){             System.gc();             pdfFile.delete();         }         //刪除產(chǎn)品文件         if(file3.exists()){             file3.delete();         }         return "success";     }

創(chuàng)建PDF附件信息拼接到主文件中:

/**      * 創(chuàng)建PDF附件信息      */     public static void createPdf() {         Document doc = null;         try {             doc = new Document();             PdfWriter.getInstance(doc, new FileOutputStream(ResourceUtils.getURL("classpath:").getPath()+TEMP_PATH));             doc.open();             BaseFont bfChi = BaseFont.createFont("STSong-Light","UniGB-UCS2-H", BaseFont.NOT_EMBEDDED);             Font fontChi = new Font(bfChi, 8, Font.NORMAL);              PdfPTable table = new PdfPTable(5);              Font fontTitle = new Font(bfChi, 15, Font.NORMAL);             PdfPCell cell = new PdfPCell(new Paragraph("*貨運*運輸服務協(xié)議-附件1 運輸費用報價",fontTitle));               cell.setColspan(5);             table.addCell(cell); //      "序號"             table.addCell(new Paragraph("序號",fontChi));             table.addCell(new Paragraph("品類",fontChi));             table.addCell(new Paragraph("名稱",fontChi));             table.addCell(new Paragraph("計算方式",fontChi));             table.addCell(new Paragraph("費率",fontChi));              table.addCell(new Paragraph("1",fontChi));             table.addCell(new Paragraph("貨運",fontChi));             table.addCell(new Paragraph("費率1.0",fontChi));             table.addCell(new Paragraph("算",fontChi));             table.addCell(new Paragraph("0~100萬-5.7%,上限:500元,下限:20元",fontChi));              table.addCell(new Paragraph("2",fontChi));             table.addCell(new Paragraph("貨運",fontChi));             table.addCell(new Paragraph("費率1.0",fontChi));             table.addCell(new Paragraph("倒",fontChi));             table.addCell(new Paragraph("100萬~200萬-5.6%,無上限、下限",fontChi));              table.addCell(new Paragraph("3",fontChi));             table.addCell(new Paragraph("貨運",fontChi));             table.addCell(new Paragraph("費率1.0",fontChi));             table.addCell(new Paragraph("算",fontChi));             table.addCell(new Paragraph("200萬~300萬-5.5%,無上限、下限",fontChi));               doc.add(table);  //      doc.add(new Paragraph("Hello World,看看中文支持不........aaaaaaaaaaaaaaaaa",fontChi));         } catch (FileNotFoundException e) {             e.printStackTrace();         } catch (DocumentException e) {             e.printStackTrace();         } catch (IOException e) {             e.printStackTrace();         } finally {             doc.close();         }     }

合同簽署:

/**      * 簽署合同      * @return      * @throws IOException      * @throws DocumentException      */     @GetMapping("addContent")     public String addContent() throws IOException, DocumentException {          BaseFont baseFont = BaseFont.createFont("STSong-Light", "UniGB-UCS2-H", BaseFont.NOT_EMBEDDED);         Font font = new Font(baseFont);          //這里可以填寫本地地址,也可以是服務器上的文件地址         PdfReader reader = new PdfReader(ResourceUtils.getURL("classpath:").getPath()+outputFileName);         PdfStamper stamper = new PdfStamper(reader, new FileOutputStream(ResourceUtils.getURL("classpath:").getPath()+endPdf));  //         PdfContentByte over = stamper.getOverContent(1);         ColumnText columnText = new ColumnText(over);          PdfContentByte over1 = stamper.getOverContent(1);         ColumnText columnText1 = new ColumnText(over1);          PdfContentByte over2 = stamper.getOverContent(1);         ColumnText columnText2 = new ColumnText(over2);           PdfContentByte over3 = stamper.getOverContent(1);         ColumnText columnText3 = new ColumnText(over3);         // llx 和 urx  最小的值決定離左邊的距離. lly 和 ury 最大的值決定離下邊的距離         // llx 左對齊         // lly 上對齊         // urx 寬帶         // ury 高度         columnText.setSimpleColumn(29, 117, 221, 16);         Paragraph elements = new Paragraph(0, new Chunk("上海壹站供應鏈有限公司"));          columnText1.setSimpleColumn(26, 75, 221, 16);         Paragraph elements1 = new Paragraph(0, new Chunk("2021年03月03日"));          columnText2.setSimpleColumn(800, 120, 200, 16);         Paragraph elements2 = new Paragraph(0, new Chunk("壹匯(江蘇)供應鏈管理有限公司蕪湖分公司"));          columnText3.setSimpleColumn(800, 74, 181, 16);         Paragraph elements3 = new Paragraph(0, new Chunk("2022年03月03日"));  //            acroFields.setField("customerSigntime", "2021年03月03日"); //                acroFields.setField("vendorSigntime", "2021年03月09日");         // 設置字體,如果不設置添加的中文將無法顯示         elements.setFont(font);         columnText.addElement(elements);         columnText.go();          elements1.setFont(font);         columnText1.addElement(elements1);         columnText1.go();          elements2.setFont(font);         columnText2.addElement(elements2);         columnText2.go();          elements3.setFont(font);         columnText3.addElement(elements3);         columnText3.go();          stamper.close();          File tempFile = new File(ResourceUtils.getURL("classpath:").getPath()+"簽署測試.pdf");          //如果是你要上傳到服務器上,填寫服務器的地址 //        String url = fileServer.uploadPdf(File2byte(tempFile)); //        log.info("url:"+url);          //如果是上傳服務器后,要刪除信息         //本地不要刪除,否則沒有文件 //        if(tempFile.exists()){ //            tempFile.delete(); //        }          return "success";     }

PDF工具類:

import com.itextpdf.text.*; import com.itextpdf.text.pdf.*; import lombok.extern.slf4j.Slf4j; import org.apache.tomcat.util.http.fileupload.IOUtils; import org.springframework.stereotype.Component;  import java.io.*; import java.util.List;  /***  * pdf 相關操作  * @author mxn  */ @Slf4j @Component public class PdfUtil {      /**      * 合并PDF文件      * @param files 文件列表      * @param output 輸出的PDF文件      */     public void mergeFileToPDF(List<File> files, File output) {         Document document = null;         PdfCopy copy = null;         OutputStream os = null;         try {             os = new FileOutputStream(output);             document = new Document();             copy = new PdfCopy(document, os);             document.open();             for (File file : files) {                 if (!file.exists()) {                     continue;                 }                 String fileName = file.getName();                 if (fileName.endsWith(".pdf")) {                     PdfContentByte cb = copy.getDirectContent();                     PdfOutline root = cb.getRootOutline();                     new PdfOutline(root, new PdfDestination(PdfDestination.XYZ), fileName                             .substring(0, fileName.lastIndexOf(".")));                     // 不使用reader來維護文件,否則刪除不掉文件,一直被占用                     try (InputStream is = new FileInputStream(file)) {                         PdfReader reader = new PdfReader(is);                         int n = reader.getNumberOfPages();                         for (int j = 1; j <= n; j++) {                             document.newPage();                             PdfImportedPage page = copy.getImportedPage(reader, j);                             copy.addPage(page);                         }                     } catch(Exception e) {                         log.warn("error to close file : {}" + file.getCanonicalPath(), e); //                        e.printStackTrace();                     }                 } else {                     log.warn("file may not be merged to pdf. name:" + file.getCanonicalPath());                 }             }         } catch (Exception e) {             e.printStackTrace();         } finally {             if (document != null) {                 document.close();             }             if (copy != null) {                 copy.close();             }             if (os != null) {                 IOUtils.closeQuietly(os);             }         }     }       /**      * 將文件轉(zhuǎn)換成byte數(shù)組      * @param file      * @return      * **/     public static byte[] File2byte(File file){         byte[] buffer = null;         try {             FileInputStream fis = new FileInputStream(file);             ByteArrayOutputStream bos = new ByteArrayOutputStream();             byte[] b = new byte[1024];             int n;             while ((n = fis.read(b)) != -1) {                 bos.write(b, 0, n);             }             fis.close();             bos.close();             buffer = bos.toByteArray();         }catch (FileNotFoundException e){             e.printStackTrace();         }catch (IOException e){             e.printStackTrace();         }         return buffer;     } }

演示

當我們編寫完成之后,就來到了最關鍵的地方,測試了,心里還有點小激動,應該不會有BUG的

怎么用Java實現(xiàn)合同模板簽署的功能

首先我們輸入  http://localhost:8080/generatePdf,生成填充模板,生成新的PDF文件并合并文件,生成完成之后我們會在項目的class目錄下看到這個文件

怎么用Java實現(xiàn)合同模板簽署的功能

打開我們的文件,就可以看到,對應的數(shù)據(jù)信息,到這里有驚無險,就查最后一步簽署合同了

怎么用Java實現(xiàn)合同模板簽署的功能

到這里如果能夠把簽署的信息,填寫到合同簽署的位置上,那我們就可以說大功告成了,我們輸入簽署的地址  http://localhost:8080/addContent,當我們在目錄下看到 簽署測試.PDF的時候就說明我們大功告成了

怎么用Java實現(xiàn)合同模板簽署的功能

怎么用Java實現(xiàn)合同模板簽署的功能

我們可以看到對應的簽署信息已經(jīng)被我們添加上去了,除了沒有第三方認證,該有的功能都有了。

以上是“怎么用Java實現(xiàn)合同模板簽署的功能”這篇文章的所有內(nèi)容,感謝各位的閱讀!希望分享的內(nèi)容對大家有幫助,更多相關知識,歡迎關注億速云行業(yè)資訊頻道!

向AI問一下細節(jié)

免責聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權內(nèi)容。

AI