Java操作PDF文件實現(xiàn)簽訂電子合同詳細教程
前言:
前兩天領導提出需求要在pdf中加入電子簽章與電子簽名,然后自己查找了一些資料完成了,今天有時間正好分享一下,希望可以幫助到大家
先看效果:
1.編寫word文件
1.1先將模板編寫出來(可以根據(jù)自己的需求編寫)我這里是測試demo
1.2然后生成PDF格式進行保存
1.3我這里是將文件保存到本地后上傳到華為云的OBS中,在本地也可以操作,我只是為了方便保存到數(shù)據(jù)庫中,可以根據(jù)自己的業(yè)務邏輯處理,效果雷同
注:這里上傳是在第二步完成后在操作
2.為PDF格式做表單
2.1然后將剛剛生成的pdf用PDF編輯器打開
注:我這里使用的是(萬興PDF)可以去找免費的使用
打開后找到表單:
文字部分:
點擊文本字段,然后和截圖一樣吧自己需要添加文字的地方圈出來
然后在屬性中設置名稱(后面代碼操作會用到)
2.2圖片表單
然后在添加圖片表單,操作和文字一樣,吧需要放圖片的地方圈出來命名
這里需要注意的就是(外觀設置無顏色,不然后面生成出來會有邊框,特別丑)
然后在選項中選為僅標簽(這樣公章就可以變的透明,可以根據(jù)自己的業(yè)務邏輯調整)
操作完成后保存
3.為表單賦值
public class PdfTest { public static void main(String[] args) { String fileName = "電子合同"; // 獲取當前時間 Date currentDate = new Date(); // 創(chuàng)建一個SimpleDateFormat對象,指定日期格式 SimpleDateFormat sdf = new SimpleDateFormat("yyyy年MM月dd日"); // 格式化當前時間 String formattedDate = sdf.format(currentDate); //獲取當前日期一年后的日期 String formattedDate2 = sdf.format(new Date(currentDate.getTime() + 365L * 24 * 60 * 60 * 1000)); System.err.println(formattedDate+"-"+formattedDate2); //測試執(zhí)行 FillTemplate( "剛剛添加表單保存的pdf文件的路徑", "保存生成的pdf文件的路徑", "XXX有限公司", "張三豐", "浙江寧波海曙區(qū)紅星大廈1706號", "李四", "18888888888", "dawdawd@163.com", formattedDate+"至"+formattedDate2, formattedDate, "簽名圖片的路徑", "蓋章的路徑" ); } // 下面的參數(shù)就是表單中的名稱,需要對應上不然找不到(需要注意大小寫) public static void FillTemplate( String sourcesPath, String targetPath, String name, String fr, String address, String phoneName, String phone, String wx, String data, String newData, String signPath, String gongzhangPath ){ //設置參數(shù) JSONObject jsonObject = new JSONObject(); jsonObject.put("name",name); jsonObject.put("fr",fr); jsonObject.put("address",address); jsonObject.put("phoneName",phoneName); jsonObject.put("phone",phone); jsonObject.put("wx",wx); jsonObject.put("data",data); jsonObject.put("newData",newData); // 填充創(chuàng)建pdf PdfReader reader = null; PdfStamper stamp = null; ByteArrayOutputStream baos =null; try { reader = new PdfReader( sourcesPath); File deskFile = new File(targetPath); stamp = new PdfStamper(reader, new FileOutputStream(deskFile)); // 取出報表模板中的所有字段 AcroFields form = stamp.getAcroFields(); System.err.println(form.getFields().keySet()); //設置宋體 BaseFont song =BaseFont.createFont("STSong-Light", "UniGB-UCS2-H", BaseFont.NOT_EMBEDDED); if (jsonObject != null) { for (Map.Entry<String, Object> entry : jsonObject.entrySet()) { String key = entry.getKey(); String value = entry.getValue().toString(); //保存選項 if (key.startsWith("select")) { form.setField(key, value, true); //保存文字 }else { form.setFieldProperty(key, "textfont", song, null); form.setField(key, value); } } } //插入簽名 insertImage(form,stamp,"sign",signPath); //插入公章 insertImage(form,stamp,"gongzhang",gongzhangPath); //保存修改 stamp.setFormFlattening(true); }catch (Exception e){ e.printStackTrace(); }finally { if (stamp != null) { try{ stamp.close(); }catch (Exception e){ e.printStackTrace(); } } if (reader != null) { try{ reader.close(); }catch (Exception e){ e.printStackTrace(); } } if (baos != null) { try{ baos.close(); }catch (Exception e){ e.printStackTrace(); } } } } /** * pdf模板插入圖片 * @param form * @param stamper * @param filedName * @param url * @return */ public static boolean insertImage(AcroFields form, PdfStamper stamper, String filedName, String url) { try { int pageNo = form.getFieldPositions(filedName).get(0).page; Rectangle signRect = form.getFieldPositions(filedName).get(0).position; float x = signRect.getLeft(); float y = signRect.getBottom(); Image image = Image.getInstance(url); // 獲取操作的頁面 PdfContentByte under = stamper.getOverContent(pageNo); // 根據(jù)域的大小縮放圖片 image.scaleToFit(signRect.getWidth(), signRect.getHeight()); // 添加圖片 image.setAbsolutePosition(x, y); under.addImage(image); }catch (Exception e){ return false; } return true; } }
4.生成文檔
然后執(zhí)行后在保存生成的pdf文件的路徑中找到文件:
點擊查看:
效果圖:
5.上傳到OBS中
需要保存到數(shù)據(jù)庫中的上傳到OSS和OBS中都可以。。。
總結
到此這篇關于Java操作PDF文件實現(xiàn)簽訂電子合同的文章就介紹到這了,更多相關Java實現(xiàn)簽訂電子合同內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
Java?InheritableThreadLocal使用示例詳解
InheritableThreadLocal繼承了ThreadLocal,此類擴展了ThreadLocal以提供從父線程到子線程的值的繼承:當創(chuàng)建子線程時,子線程接收父線程具有的所有可繼承線程局部變量的初始值。?通常子線程的值與父線程的值是一致的2022-09-09Spring中ApplicationContext的拓展功能詳解
這篇文章主要介紹了Spring中ApplicationContext的拓展功能詳解,相對于BeanFactory來說,ApplicationContext除了提供BeanFactory的所有功能外,還有一些其他的功能,主要包括國際化支持、資源訪問、事件傳遞,需要的朋友可以參考下2024-01-01淺談一下RabbitMQ、Kafka和RocketMQ消息中間件對比
這篇文章主要介紹了淺談一下RabbitMQ、Kafka和RocketMQ消息中間件對比,消息中間件屬于分布式系統(tǒng)中一個字系統(tǒng),關注于數(shù)據(jù)的發(fā)送和接收,利用高效可靠的異步信息傳遞機制對分布式系統(tǒng)中的其余各個子系統(tǒng)進行集成,需要的朋友可以參考下2023-05-05Java如何將任意類型的Object對象轉換為相應的實體對象
這篇文章主要介紹了Java如何將任意類型的Object對象轉換為相應的實體對象問題,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教2024-01-01解析springBoot-actuator項目構造中health端點工作原理
這篇文章主要介紹了springBoot-actuator中health端點工作原理,對spring-boot-actuator的項目構造,工作原理進行了全面的梳理,側重health健康檢查部分2022-02-02SpringCloud Zuul網(wǎng)關功能實現(xiàn)解析
這篇文章主要介紹了SpringCloud Zuul網(wǎng)關功能實現(xiàn)解析,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下2020-03-03