用Adobe Acrobat DC快速生成合同模板、itext导出pdf,解决项目中合同问题

本文介绍如何使用iText工具库生成带有中文的合同PDF文件,包括制作合同模板、准备必要的jar包以及具体代码实现过程。

关于利用itext生成合同


1、 制作合同模板

1、    制作模板可以直接利用一款软件(Adobe Acrobat DC),可以在网上找免费破解版的,如果没有找到合适的版本,可以去我的百度云盘下载,地址:链接: http://pan.baidu.com/s/1c3qYj8 密码: xewr,软件安装这里就不说了。

2、    打开Adobe Acrobat DC,选择工具—准备表单

3、    选择文件—开始 ,然后进入模板制作界面。

4、    在需要填入内容处,填入对应的字段,如name,idCard…等,关于填字段的一些常用方法技巧,可参考附件2- Adobe Acrobat DC字段填入方法。模板制作完成后,就可以进入代码开发了。

 

2、 jar包准备

1、在这里,我选择itextpdf -5.5.10.jar和itext-asian-5.2.0.jar

需要注意下,如果用其他jar报错了,要改回我这个版本的,因为有的jar后期版本结构改变了,与asian结构不一致,会导致设置字体时候报错,建议使用以上两个版本jar。

<itextpdf.version>5.5.10</itextpdf.version>

<itext-asian.version>5.2.0</itext-asian.version>

 

<!-- itext 生成合同pdf -->

                            <dependency>

                                <groupId>com.itextpdf</groupId>

                                <artifactId>itextpdf</artifactId>

                                <version>${itextpdf.version}</version>

                            </dependency>

                            <dependency>

                                <groupId>com.itextpdf</groupId>

                                <artifactId>itext-asian</artifactId>

                                <version>${itext-asian.version}</version>

                            </dependency>

3、 代码实现部分

1、控制层部分loanBaseController

      @RequiresPermissions("loan:loanBase:edit")

      @RequestMapping(value= "downloadContract")

      publicvoid createContract (String loanBaseId,HttpServletRequest request,HttpServletResponseresponse){

                    Map<String,Object> dataMap = new HashMap<String,Object>();

                    loanContractService.getData(dataMap,loanBaseId); // 对模板中填入的字段设置对应的value

                            //我这里是把模板放在maven项目的WeB_INF/pdf/common目录下,并且需要部署到linux上,因此路径的获取可能与其他存在差异,下面只是为了获取pdf模板的地址,便于后面生成输入流

                    StringrealPath = request.getSession().getServletContext().getRealPath("/");

                    StringpropertyPath =realPath+"WEB-INF"+File.separatorChar+"pdf"+File.separatorChar+"common";

                    StringfileName = “借款协议.pdf”;

                    StringtemplatePDF = propertyPath+File.separatorChar+fileName;

                    try{

                                  InputStreamis = new FileInputStream(new File(templatePDF)); // pdf模板的输入流

                                  ServletOutputStreamoutputStream = response.getOutputStream(); // 生成的新pdf输出流

                                  response.setHeader("Content-Disposition","attachment;fileName=" + URLEncoder.encode(fileName,"UTF-8"));

                                  loanContractService.doSomeThing(is,outputStream, dataMap); // 调用方法生成新的合同

                    }catch (Exception e1) {

                                  e1.printStackTrace();

                    }                                        

}

2、控制层部分LoanContractService

package com.***;

import java.io.ByteArrayOutputStream;

import java.io.FileNotFoundException;

import java.io.IOException;

import java.io.InputStream;

import java.util.Date;

import java.util.Iterator;

import java.util.List;

import java.util.Map;

import java.util.Set;

 

import javax.annotation.Resource;

import javax.servlet.ServletOutputStream;

 

importorg.springframework.stereotype.Service;

importorg.springframework.transaction.annotation.Transactional;

 

import com.itextpdf.text.Document;

import com.itextpdf.text.DocumentException;

import com.itextpdf.text.pdf.AcroFields;

import com.itextpdf.text.pdf.BaseFont;

import com.itextpdf.text.pdf.PdfCopy;

importcom.itextpdf.text.pdf.PdfImportedPage;

import com.itextpdf.text.pdf.PdfReader;

import com.itextpdf.text.pdf.PdfStamper;

import com.kkyc.sass.common.utils.DateUtils;

importcom.kkyc.sass.common.utils.DoubleUtil;

importcom.kkyc.sass.common.utils.MoneyUtils;

importcom.kkyc.sass.common.utils.StringUtils;

importcom.kkyc.sass.modules.finance.entity.FinanceBase;

importcom.kkyc.sass.modules.finance.entity.FinanceReturn;

importcom.kkyc.sass.modules.finance.service.FinanceBaseService;

importcom.kkyc.sass.modules.finance.service.FinanceReturnService;

importcom.kkyc.sass.modules.loan.dao.LoanCarDao;

import com.kkyc.sass.modules.loan.entity.BaseCar;

importcom.kkyc.sass.modules.loan.entity.BaseUser;

importcom.kkyc.sass.modules.loan.entity.LoanBase;

importcom.kkyc.sass.modules.loan.entity.LoanCar;

importcom.kkyc.sass.modules.loan.entity.LoanProduct;

import com.kkyc.sass.modules.loan.entity.LoanProductAddition;

importcom.kkyc.sass.modules.loan.entity.LoanUser;

importcom.kkyc.sass.modules.sys.utils.DictUtils;

 

/**

 * 合同操作Service

 *@author wuyp

 *@version 2017-03-07

 */

@Service

@Transactional(readOnly = true)

public class LoanContractService {

      @Resource

      privateBaseCarService baseCarService;

     

      publicvoid getData(Map<String, Object> dataMap, String loanBaseId) { 

                    LoanBaseloanBase = loanBaseService.get(loanBaseId);

                    //1.借款协议

                                  dataMap.put("orderNum",loanBase.getOrderNum());

                                  dataMap.put("userName",***);

                                  dataMap.put("idCard",***);

                                  dataMap.put("userNameB",***);

                                  dataMap.put("idCardB",***);

                    }            

      /**

       * 赋值并生成新的PDF文档

       * @param is   pdf模版输入流

       * @param os   输出的新PDF流

       * @param hashMap    pdf模板对应的数据

       * @author wuyp

       */

      publicvoid doSomeThing(InputStream is,ServletOutputStream os,Map<String,Object>hashMap){

                    try{                                               

                                  PdfReaderreader = new PdfReader(is);  // 读取并解析pdf模板。

                                  ByteArrayOutputStreambaos = new ByteArrayOutputStream(); // 创建一个新的字节数组输出流,缓冲容量为32字节,在必要时会增加

                                  PdfStamperstamp = new PdfStamper(reader,baos);  // 开始添加额外的过程内容到现有的PDF文档。

                                  AcroFieldsform = stamp.getAcroFields();  // 获取允许设置值的AcroFields对象

                                  form=setField(form,hashMap);                    

                                  stamp.setFormFlattening(true);// 如果为false那么生成的PDF文件还能编辑,一定要设为true

                                  stamp.close();

                                  Documentdoc = new Document();

                                  PdfCopypdfCopy = new PdfCopy(doc, os); // itext中合并页面的工具类

                                  doc.open();

                                  for(int i = 1; i <= reader.getNumberOfPages(); i++) {

                                                PdfImportedPageimpPage = pdfCopy.getImportedPage(new PdfReader(baos.toByteArray()), i); // 从pdf模板中抓取第i个页面

                                                pdfCopy.addPage(impPage);// 合并页面

                                  }

                                  doc.close();                                

                                  os.flush();       

                    }catch (FileNotFoundException e) {

                                  e.printStackTrace();

                    }catch (IOException e) {

                                  e.printStackTrace();

                    }catch (DocumentException e) {

                                  e.printStackTrace();

                    }

                   

      }

      /**

       * 对模板中字段设置对应的value

       * @Description (详细说明)

       * @param form

       * @param hashMap

       * @return

       * @Date 2017年3月29日 下午1:48:25

       */

      @SuppressWarnings("unchecked")

      publicstatic  AcroFields setField(AcroFieldsform,Map<String,Object> hashMap) {

                    Set<String>it = hashMap.keySet();

                    Iterator<String>itr = it.iterator();

                    while(itr.hasNext()){

                                  try{

                                                Objecttemp = itr.next();

                                                BaseFontbf =BaseFont.createFont("STSong-Light","UniGB-UCS2-H",BaseFont.NOT_EMBEDDED);  // 创建字体 

                                                form.setFieldProperty(temp.toString(),"textfont", bf, null); // 设置字体

                                                form.setFieldProperty(temp.toString(),"textsize", (float) 8, null); // 设置字体大小

                                                /*BaseColorred = BaseColor.RED;   // 设置字体颜色

                                                form.setFieldProperty(temp.toString(),"textcolor", red, null);*/

                                                form.setField(temp.toString(),(String)hashMap.get(temp.toString()));

                                  } catch (IOException e) {

                                                e.printStackTrace();

                                  }catch (DocumentException e) {

                                                e.printStackTrace();

                                  }

                    }

                    returnform;

      }

}

 

结束。。。

关于doSomeThing中的参数可以灵活配置,比如传入模板的路径,生成文件的路径,也是可以的,只需要能读取到pdf模板即可,例如pdfReader类中有很多构造方法可以读取解析文档,PdfReader pdfReader = new PdfReader(url);

附件下载地址:附件1-使用itext生pdf详解  http://download.youkuaiyun.com/detail/w20228396/9797795


<think>我们被要求使用Spring Boot和iText库根据模板生成PDF文件。根据引用[2],我们可以使用Adobe Acrobat Pro DC创建PDF模板,然后在Spring Boot中使用iText填充数据。 步骤: 1. 使用Adobe Acrobat Pro DC创建模板:在PDF中创建表单域(文本域、复选框等),并命名每个域。保存为模板文件(例如:template.pdf)。 2. 将模板文件放入Spring Boot项目的资源目录(如:src/main/resources/templates/)。 3. 添加依赖:在pom.xml中添加iText依赖(注意:我们使用iText7,但根据引用[2]可能是使用iText5?这里我们以iText7为例,因为它是较新版本,但需要根据实际情况选择。如果引用[2]中的模板是用Acrobat创建的,那么iText5和7都可以处理,但API不同。这里我们使用iText7,因为它是当前推荐版本,但请注意,如果用户使用的是旧版iText,可能需要调整代码)。 如果使用iText7,添加以下依赖(注意:iText7有多个模块): ```xml <dependency> <groupId>com.itextpdf</groupId> <artifactId>itext7-core</artifactId> <version>7.2.5</version> <type>pom</type> </dependency> ``` 另外,我们还需要处理表单填充的模块,即`forms`模块: ```xml <dependency> <groupId>com.itextpdf</groupId> <artifactId>forms</artifactId> <version>7.2.5</version> </dependency> ``` 4. 编写服务类来生成PDF。 实现方法: 我们将创建一个PDF服务类,其中包含一个方法,该方法读取模板文件,然后使用PdfAcroForm来填充表单域,最后输出PDF。 注意:由于模板文件在资源目录中,我们需要使用ClassPathResource来读取。 代码示例: ```java import com.itextpdf.forms.PdfAcroForm; import com.itextpdf.forms.fields.PdfFormField; import com.itextpdf.kernel.pdf.PdfDocument; import com.itextpdf.kernel.pdf.PdfReader; import com.itextpdf.kernel.pdf.PdfWriter; import org.springframework.core.io.ClassPathResource; import org.springframework.stereotype.Service; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.util.Map; @Service public class PdfService { public void generatePdf(OutputStream outputStream, Map<String, String> formData) throws IOException { // 加载模板文件 ClassPathResource resource = new ClassPathResource("templates/template.pdf"); InputStream inputStream = resource.getInputStream(); // 初始化PdfReader和PdfWriter PdfReader reader = new PdfReader(inputStream); PdfWriter writer = new PdfWriter(outputStream); PdfDocument pdfDoc = new PdfDocument(reader, writer); // 获取表单 PdfAcroForm form = PdfAcroForm.getAcroForm(pdfDoc, true); // 填充表单数据 Map<String, PdfFormField> fields = form.getFormFields(); for (Map.Entry<String, String> entry : formData.entrySet()) { String fieldName = entry.getKey(); String value = entry.getValue(); PdfFormField field = fields.get(fieldName); if (field != null) { field.setValue(value); } } // 如果不需要表单可编辑,可以将其扁平化(这样表单域就变成普通文本) form.flattenFields(); // 关闭文档 pdfDoc.close(); } } ``` 5. 在控制器中调用此服务,生成PDF并返回给前端预览(例如,通过HTTP响应)。 控制器示例: ```java import org.springframework.beans.factory.annotation.Autowired; import org.springframework.core.io.InputStreamResource; import org.springframework.http.HttpHeaders; import org.springframework.http.MediaType; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RestController; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.util.HashMap; import java.util.Map; @RestController public class PdfController { @Autowired private PdfService pdfService; @GetMapping("/generatePdf") public ResponseEntity<InputStreamResource> generatePdf() throws IOException { // 模拟数据 Map<String, String> data = new HashMap<>(); data.put("name", "张三"); data.put("age", "30"); // 其他表单域数据... ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); pdfService.generatePdf(outputStream, data); byte[] pdfBytes = outputStream.toByteArray(); HttpHeaders headers = new HttpHeaders(); headers.add(HttpHeaders.CONTENT_DISPOSITION, "inline; filename=generated.pdf"); return ResponseEntity .ok() .headers(headers) .contentType(MediaType.APPLICATION_PDF) .body(new InputStreamResource(new ByteArrayInputStream(pdfBytes))); } } ``` 这样,当访问/generatePdf时,就会生成PDF并在浏览器中预览。 注意事项: - 模板中的表单域名称必须与代码中使用的键一致。 - 如果需要生成多页,确保模板中已经设计好分页,并且表单域名称唯一(如果同一名称出现在多页,则都会被填充相同值)。 - 如果表单域是复选框,设置值应为"On"(或根据模板中定义的导出值)来勾选,否则为"Off"。 - 使用扁平化(flattenFields)后,表单域将变成静态内容,无法再编辑。如果不调用此方法,则生成PDF表单仍可编辑。 以上代码基于iText7。如果使用iText5,代码会有所不同,但思路类似:使用PdfStamper和AcroFields。 如果用户需要使用iText5,那么依赖和代码将不同。这里给出iText5的依赖和代码片段(供参考): 依赖(iText5): ```xml <dependency> <groupId>com.itextpdf</groupId> <artifactId>itextpdf</artifactId> <version>5.5.13.3</version> </dependency> ``` iText5代码示例(PdfService内): ```java import com.itextpdf.text.DocumentException; import com.itextpdf.text.pdf.AcroFields; import com.itextpdf.text.pdf.PdfReader; import com.itextpdf.text.pdf.PdfStamper; import org.springframework.core.io.ClassPathResource; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStream; import java.util.Map; public byte[] generatePdfWithIText5(Map<String, String> formData) throws IOException, DocumentException { ClassPathResource resource = new ClassPathResource("templates/template.pdf"); InputStream inputStream = resource.getInputStream(); PdfReader reader = new PdfReader(inputStream); ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); PdfStamper stamper = new PdfStamper(reader, outputStream); AcroFields form = stamper.getAcroFields(); // 填充表单 for (Map.Entry<String, String> entry : formData.entrySet()) { String fieldName = entry.getKey(); String value = entry.getValue(); form.setField(fieldName, value); } // 如果扁平化,则表单域变成普通文本 stamper.setFormFlattening(true); stamper.close(); reader.close(); return outputStream.toByteArray(); } ``` 在控制器中调用即可。 总结:根据项目需求选择iText版本。本文提供了iText7和iText5两种实现方式,但推荐使用iText7,因为它是当前活跃开发的版本。 引用说明: [^1]: 介绍了Spring Boot和iTextPdf生成PDF的背景。 [^2]: 提供了使用PDF模板生成文件的方法,并提到了使用Adobe Acrobat Pro DC创建模板。 注意:上述代码仅为示例,实际应用中需要处理异常、资源关闭等。 生成相关问题: 1. 如何使用Adobe Acrobat Pro DC创建PDF表单模板? 2. 在Spring Boot中生成PDF时如何处理中文字体? 3. 如何动态生成多页PDF(例如根据列表数据生成多行)? 4. iText5和iText7的主要区别是什么?如何选择? 5. 除了iText,还有哪些Java库可以用于生成PDF?</think>### Spring Boot中使用iText库根据模板生成PDF文件的实现方法 在Spring Boot中使用iText库根据模板生成PDF文件,主要分为三个核心步骤: #### 1. **准备PDF模板** - 使用Adobe Acrobat Pro DC创建带表单域的PDF模板: - 添加文本域(命名如`name_field`、`date_field`) - 添加复选框/单选按钮(命名如`agree_checkbox`) - 将模板文件(如`template.pdf`)放入`src/main/resources/templates/`目录[^2] #### 2. **添加依赖** 在`pom.xml`中添加iText依赖(推荐iText 7+): ```xml <dependency> <groupId>com.itextpdf</groupId> <artifactId>itext7-core</artifactId> <version>7.2.5</version> </dependency> <dependency> <groupId>com.itextpdf</groupId> <artifactId>forms</artifactId> <version>7.2.5</version> </dependency> ``` #### 3. **核心代码实现** ```java @Service public class PdfGeneratorService { public byte[] generatePdfFromTemplate(Map<String, String> formData) throws IOException { // 1. 加载模板 ClassPathResource templateResource = new ClassPathResource("templates/template.pdf"); ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); try (PdfReader reader = new PdfReader(templateResource.getInputStream()); PdfWriter writer = new PdfWriter(outputStream); PdfDocument pdfDoc = new PdfDocument(reader, writer)) { // 2. 获取表单对象 PdfAcroForm form = PdfAcroForm.getAcroForm(pdfDoc, true); // 3. 填充表单数据 formData.forEach((fieldName, value) -> { PdfFormField field = form.getField(fieldName); if (field != null) { field.setValue(value); } }); // 4. 扁平化表单(使字段不可编辑) form.flattenFields(); } return outputStream.toByteArray(); } } ``` #### 4. **控制器调用示例** ```java @RestController public class PdfController { @Autowired private PdfGeneratorService pdfService; @GetMapping("/generate-pdf") public ResponseEntity<byte[]> generatePdf() throws IOException { // 构建动态数据 Map<String, String> formData = new HashMap<>(); formData.put("name_field", "张三"); formData.put("date_field", "2023-10-15"); formData.put("agree_checkbox", "Yes"); byte[] pdfBytes = pdfService.generatePdfFromTemplate(formData); // 设置响应头 HttpHeaders headers = new HttpHeaders(); headers.setContentType(MediaType.APPLICATION_PDF); headers.setContentDisposition(ContentDisposition.inline().filename("output.pdf").build()); return new ResponseEntity<>(pdfBytes, headers, HttpStatus.OK); } } ``` #### 关键注意事项: 1. **表单域匹配** 模板中的字段名称必须与代码中的`fieldName`完全一致(区分大小写) 2. **中文支持** 需添加中文字体依赖: ```xml <dependency> <groupId>com.itextpdf</groupId> <artifactId>font-asian</artifactId> <version>7.2.5</version> </dependency> ``` 在填充前设置字体: ```java PdfFont font = PdfFontFactory.createFont("STSong-Light", "UniGB-UCS2-H"); field.setFont(font); ``` 3. **动态表格处理** 如需在模板外追加动态内容(如表格),可在扁平化后添加新页面: ```java PdfPage newPage = pdfDoc.addNewPage(); try (Canvas canvas = new Canvas(newPage, pdfDoc.getDefaultPageSize())) { canvas.add(new Paragraph("动态表格").setFont(font)); // 添加表格逻辑... } ``` 4. **性能优化** - 使用`ByteArrayOutputStream`避免磁盘I/O - 模板文件预加载到内存(适用于高频调用) - 对于复杂模板,考虑使用`PdfDocument`的增量更新模式 [^1]: 在现代应用程序开发中,生成PDF文件是一个常见的需求... [^2]: SpringBoot 基于iText 根据PDF模板动态生成文件... --- ### 相关问题 1. **如何处理PDF模板中的动态表格数据?** 当需要在模板基础上追加动态表格时,应如何实现行列数据的灵活生成? 2. **如何解决iText生成PDF的中文乱码问题?** 使用中文字体时有哪些注意事项?不同操作系统下字体配置有何差异? 3. **在微服务架构中如何优化PDF生成性能?** 高并发场景下有哪些缓存策略和资源复用方案? 4. **如何实现PDF模板的动态版本管理?** 当业务需要频繁更新模板时,如何设计版本控制系统? 5. **除了iText,还有哪些Java库支持模板PDF生成?** 如Apache PDFBox、Flying Saucer等替代方案的优缺点比较。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值