项目有生成PDF的需求,虽然做过,但是再次遇到了还是会卡壳,特此记录全过程。
一、模板的创建
首先定义好一个docx文档,然后转成PDF格式输出保存
然后用 Adobe Acrobat 工具将 PDF放进去加入表单域
具体操作如下
点击后会有一个创建选项,创建选项里有一个创建表单选项,点进去
选择一个文件,选择导出的PDF模板
红标标注的文本域,可以手动确定范围。
选择的文件,在默认空着的地方会自动生成的,如果需要值要改一下名就好,大小写敏感,推荐用驼峰命名规则。
这样一个模板就定义好了,直接找个地方,能访问到的地方就好了。
二、代码部分
导入依赖
<!-- PDF导出的maven依赖 -->
<!-- https://mvnrepository.com/artifact/com.itextpdf/itextpdf -->
<dependency>
<groupId>com.itextpdf</groupId>
<artifactId>itextpdf</artifactId>
<version>5.5.13</version>
</dependency>
<dependency>
<groupId>com.itextpdf</groupId>
<artifactId>itext-asian</artifactId>
<version>5.2.0</version>
</dependency>
主要代码
@Override
public String OtherInOrOut(Long otherHeadId, HttpServletResponse response) throws UnsupportedEncodingException {
HlOtherDepotHead hlOtherDepotHead = hlOtherDepotHeadService.selectHlOtherDepotHeadByOtherHeadId(otherHeadId);
HlSupplierInfo hlSupplierInfo = null;
HlCustomerInfo hlCustomerInfo = null;
if (hlOtherDepotHead.getType() == 0) {
hlSupplierInfo = hlSupplierInfoService.selectHlSupplierInfoBySupplierInfoId(hlOtherDepotHead.getComefromInfoId());
}
if (hlOtherDepotHead.getType() == 1) {
hlCustomerInfo = hlCustomerInfoService.selectHlCustomerInfoByCustomerId(hlOtherDepotHead.getComefromInfoId());
}
// 使用哪套简历模板
String pathFileName = "static/template/noeOtherInOrOut.pdf";
String fileName = "泓ERP";
// 导出格式
response.setContentType("application/pdf");
response.setHeader("Content-Disposition", "attachment;fileName="+fileName+".pdf"
+ URLEncoder.encode(pathFileName, "UTF-8"));
try {
OutputStream os = response.getOutputStream();
// 2 读入pdf表单
PdfReader reader = new PdfReader(pathFileName);
// 3 根据表单生成一个新的pdf w
PdfStamper ps = new PdfStamper(reader, os);
// 4 获取pdf表单
AcroFields form = ps.getAcroFields();
// 5给表单添加中文字体 这里采用系统字体。不设置的话,中文可能无法显示
// BaseFont bf = BaseFont.createFont("C:/WINDOWS/Fonts/SIMSUN.TTC,1", BaseFont.IDENTITY_H, BaseFont.EMBEDDED); // win
BaseFont bf = BaseFont.createFont("STSong-Light", "UniGB-UCS2-H", BaseFont.NOT_EMBEDDED); // linux
form.addSubstitutionFont(bf);
Map<String, String> map = setMsaBusinessToForm(corresponding(hlOtherDepotHead, hlSupplierInfo, hlCustomerInfo));
for (String key : map.keySet()) {
String value = (String) map.get(key);
form.setFieldProperty(key,"textfont", bf,null);
form.setField(key, value); // 为字段赋值,注意字段名称是区分大小写的
}
ps.setFormFlattening(true);
System.out.println("*******************PDF导出成功***********************");
} catch (Exception e) {
System.out.println("*******************PDF导出失败***********************");
e.printStackTrace();
} finally {
try {
ps.close();
reader.close();
os.close();
} catch (Exception e) {
e.printStackTrace();
}
}
return null;
}
setMsaBusinessToForm方法详情
public Map<String, String> setMsaBusinessToForm(OtherInOrOutDto dto) throws DocumentException, IOException {
Map<String, String> data = new HashMap<String, String>();
// key必须和模板中定义的key名对应上,value是要替换key的数据, value必须为String
data.put("模板的key", value);
List<OtherInOrOutItemDto> itemDtos = dto.getItemDtos();
int i = 1;
//如果是list的话
for (OtherInOrOutItemDto itemDto : itemDtos) {
data.put("index" + i, itemDto.getIndex().toString());//序号
i++;
}
return data;
}
corresponding 方法详情
public OtherInOrOutDto corresponding(HlOtherDepotHead hlOtherDepotHead, HlSupplierInfo hlSupplierInfo, HlCustomerInfo hlCustomerInfo){
OtherInOrOutDto dto = new OtherInOrOutDto();
//这个方法里是处理业务的逻辑,单独拿出来了
//查询的数据
String deptName = deptService.getParentDeptName();
//数据存入实体
dto.setDeptName(deptName);
//返回
return dto;
}
corresponding 负责处理数据,将处理好的数据交给 setMsaBusinessToForm 方法
setMsaBusinessToForm方法将数据放入map中,将map返回给上层调用者,进行如下处理
//循环map的key
for (String key : map.keySet()) {
String value = (String) map.get(key);
form.setFieldProperty(key,"textfont", bf,null);
form.setField(key, value); // 为字段赋值,注意字段名称是区分大小写的
}
//导出操作
ps.setFormFlattening(true);
最后勿忘关闭资源