使用itext插件根据PDF模版生成PDF版电子合同并实现双方互签
说明:
项目需要在小程序上面可以甲乙方签合同的功能。
谦谦记录一下整个逻辑
1(移动端)申请——2(PC端审核)审核通过后——3(PC端匹配)匹配通过后——4(PC端制作合同)制作合同之后——5(移动端签约)
需要的依赖
<!-- https://mvnrepository.com/artifact/com.itextpdf/itextpdf pdf签合同-->
<dependency>
<groupId>com.itextpdf</groupId>
<artifactId>itextpdf</artifactId>
<version>5.5.11</version>
</dependency>
<!-- https://mvnrepository.com/artifact/com.itextpdf/itext-asian pdf签合同 -->
<dependency>
<groupId>com.itextpdf</groupId>
<artifactId>itext-asian</artifactId>
<version>5.2.0</version>
</dependency>
2.设置表单数据+图片签名
public static String signContract(SignContractEnity signContractEnity)throws Exception {
String urls="";
// 模版文件 本地
// String templateFilePath = "C:\\Users\\Administrator\\Desktop\\学习笔记\\签名v3.pdf";
//模板文件 url地址(就是服务器上的合同模板)
String templateFilePath =signContractEnity.getTemplateFilePath();
// 保存PDF文件 上传到服务器,可不用该字段
String pdfFilePath = "C:\\Users\\Administrator\\Desktop\\学习笔记\\签名.pdf";
// 表单数据
HashMap<String,String> data = new HashMap<>();
if(StringUtil.isNotBlank(signContractEnity.getContractNum())){
data.put("contractNum",signContractEnity.getContractNum());
}
if(StringUtil.isNotBlank(signContractEnity.getAmount())){
data.put("amount",signContractEnity.getAmount());
}
if(StringUtil.isNotBlank(signContractEnity.getCurrency())){
data.put("currency",signContractEnity.getCurrency());
}
if(StringUtil.isNotBlank(signContractEnity.getUseto())){
data.put("useto",signContractEnity.getUseto());
}
if(StringUtil.isNotBlank(signContractEnity.getMonth())){
data.put("month",signContractEnity.getMonth());
}
if(StringUtil.isNotBlank(signContractEnity.getBeginTime())){
data.put("begin_date",signContractEnity.getBeginTime());
}
if(StringUtil.isNotBlank(signContractEnity.getEndTime())){
data.put("end_date",signContractEnity.getEndTime());
}
if(StringUtil.isNotBlank(signContractEnity.getRate())){
data.put("rate",signContractEnity.getRate());
}
// 图片签名
HashMap<String,String> imageData = new HashMap<>();
//https://nttengyuankeji320623197011011455.oss-cn-shanghai.aliyuncs.com/realused/签名.jpg
if(StringUtil.isNotBlank(signContractEnity.getSign1())){
imageData.put("sign1",signContractEnity.getSign1());
}
if(StringUtil.isNotBlank(signContractEnity.getSign2())){
imageData.put("sign2",signContractEnity.getSign2());
}
// 根据PDF模版生成PDF文件
urls = createPDF(templateFilePath,data,imageData,true,pdfFilePath);
return urls;
}
/**
* 根据PDF模版生成PDF文件
* @param templateFilePath PDF模版文件路径
* @param data 表单数据
* @param imageData 图片数据 VALUE为图片文件路径
* @param formFlattening false:生成后的PDF文件表单域仍然可编辑 true:生成后的PDF文件表单域不可编辑
* @param pdfFilePath 生成PDF的文件路径
*/
private static void createPDF(String templateFilePath, HashMap<String,String> data, HashMap<String,String> imageData,
boolean formFlattening, String pdfFilePath) throws Exception{
PdfReader reader = null;
ByteArrayOutputStream bos = null;
PdfStamper pdfStamper = null;
FileOutputStream fos = null;
try{
// 读取PDF模版文件
reader = new PdfReader(templateFilePath);
// 输出流
bos = new ByteArrayOutputStream();
// 构建PDF对象
pdfStamper = new PdfStamper(reader, bos);
// 获取表单数据
AcroFields form = pdfStamper.getAcroFields();
// 使用中文字体 使用 AcroFields填充值的不需要在程序中设置字体,在模板文件中设置字体为中文字体 Adobe 宋体 std L
BaseFont bfChinese = BaseFont.createFont("STSongStd-Light", "UniGB-UCS2-H", BaseFont.NOT_EMBEDDED);
form.addSubstitutionFont(bfChinese);
// 表单赋值
for(String key : data.keySet()){
form.setField(key,data.get(key));
// 也可以指定字体
form.setFieldProperty(key, "textfont", bfChinese, null);
}
// 添加图片
if(null != imageData && imageData.size() > 0){
for(String key : imageData.keySet()){
int pageNo = form.getFieldPositions(key).get(0).page;
Rectangle signRect = form.getFieldPositions(key).get(0).position;
float x = signRect.getLeft();
float y = signRect.getBottom();
// 读图片
Image image = Image.getInstance(imageData.get(key));
// 获取操作的页面
PdfContentByte under = pdfStamper.getOverContent(pageNo);
// 根据域的大小缩放图片
image.scaleToFit(signRect.getWidth(), signRect.getHeight());
// 添加图片
image.setAbsolutePosition(x, y);
under.addImage(image);
}
}
// 如果为false那么生成的PDF文件还能编辑,一定要设为true
pdfStamper.setFormFlattening(formFlattening);
pdfStamper.close();
/*上传到服务器上走这段***************************************************** 开始*/
// 将图像输出到输出流中。
MultipartFile multipartFile =new MockMultipartFile("test.pdf","test.pdf","", bos.toByteArray());
String urls = updateHead(multipartFile);
System.out.println("---------------------- 上传至oss存储服务器"+urls);
/*上传到服务器上走这段***************************************************** 结束*/
/*保存本地走这段***************************************************** 开始*/
fos = new FileOutputStream(pdfFilePath);
fos.write(bos.toByteArray());
fos.flush();
/*保存本地走这段***************************************************** 结束*/
}finally {
if(null != fos){
try {fos.close(); }catch (Exception e){e.printStackTrace();}
}
if(null != bos){
try {bos.close(); }catch (Exception e){e.printStackTrace();}
}
if(null != reader){
try {reader.close(); }catch (Exception e){e.printStackTrace();}
}
}
}
3.制作合同模板 用word制作一个待填写调文档——另存为PDF文件——用编辑PDF的文件制作合同模板 ,这里我是参考法大大的合同模板,如果有疑问可以点开看一下,上面还挺详细https://open.fadada.com/index.html#/portal/documentCenter/HWXSMPIP30/4NA2IQQ6V2B1PEAT
4.到这里就结束了,正常调用就可以了。我的文笔不好,如有不怎么理解还请多多谅解,在下方留言即可,留言必回