场景:java中使用Itext导出pdf
前期准备:下载Adobe Acrobat DC 软件 前期制作需要导出的pdf模板
模板制作步骤
-
先在word文档上制作出自己需要的模板样式,例如:
-
-
把该word保存成pdf格式,然后再用软件打开
-
给需要填值的地方添加文本域,并填上代码中对应的字段
-
最后另存到需要存放的地址,格式为pdf
具体代码实现
依赖
<dependency>
<groupId>com.itextpdf</groupId>
<artifactId>itextpdf</artifactId>
<version>5.5.10</version>
</dependency>
<dependency>
<groupId>com.itextpdf</groupId>
<artifactId>itext-asian</artifactId>
<version>5.2.0</version>
</dependency>
这里要注意,依赖一定要添加到工具类或者具体实现的模块项目,并且两个必须添加
(昨天只添加了第一个依赖,代码不报错,但导出的pdf文件没有值,死活找不到问题)
工具类
public class PdfUtil {
/**
*
* @param o 写入的数据
* @param out 自定义保存pdf的文件流
* @param templatePath pdf模板路径
*/
// 利用模板生成pdf
public void fillTemplate(Map<String,Object> o, OutputStream out, String templatePath) {
PdfReader reader;
ByteArrayOutputStream bos;
PdfStamper stamper;
try {
reader = new PdfReader(templatePath);// 读取pdf模板
bos = new ByteArrayOutputStream();
stamper = new PdfStamper(reader, bos);
AcroFields form = stamper.getAcroFields();
java.util.Iterator<String> it = form.getFields().keySet().iterator();
while (it.hasNext()) {
String name = it.next().toString();
String value = o.get(name)!=null?o.get(name).toString():"";
form.setField(name,value);
}
stamper.setFormFlattening(true);// 如果为false那么生成的PDF文件还能编辑,一定要设为true
stamper.close();
Document doc = new Document();
// Font font = new Font(bf, 32);
PdfCopy copy = new PdfCopy(doc, out);
doc.open();
PdfImportedPage importPage = copy.getImportedPage(new PdfReader(bos.toByteArray()), 1);
copy.addPage(importPage);
doc.close();
} catch (IOException e) {
System.out.println(e);
} catch (DocumentException e) {
System.out.println(e);
}
}
}
这里需要注意一下,这串代码只会导出一页,如果想导出多页,则需把代码改成
//改成这样就不会只显示一页了。
PdfImportedPage importPage = null;
///循环是处理成品只显示一页的问题
for (int i=1;i<=reader.getNumberOfPages();i++){
importPage = copy.getImportedPage(new PdfReader(bos.toByteArray()), i);
copy.addPage(importPage);
}
具体controller代码
public AjaxResult exportRecord(@PathVariable("recordId") String recordId,HttpServletResponse response) throws IOException {
String fileName = FileUtils.encodingPdfFilename("******"); //导出时具体的文件名
CykEnterpriseReportRecord cykEnterpriseReportRecord = cykEnterpriseReportRecordService.selectCykEnterpriseReportRecordByReportRecordId(recordId);
String templateFileName = "";
templateFileName = EcenterConfig.getProfile() + "/template_endwise.pdf";//找到pdf模板
//这个是查询出来的实体类,如果是其他类型的也改成String类型的就可
String json = JSONObject.toJSONString(cykEnterpriseReportRecord);
try {
json = java.net.URLDecoder.decode(json,"UTF-8"); //解码
} catch (UnsupportedEncodingException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
JSONObject jsonObject = JSONObject.parseObject(json);
Map<String, Object> mapJson = (Map<String, Object>) JSONObject.toJSON(jsonObject);
// 设置response参数,可以打开下载页面
response.reset();
response.setCharacterEncoding("UTF-8");
// 定义输出类型
response.setContentType("application/PDF;charset=utf-8");
response.setHeader("Content-Disposition", "attachment; filename=" + "assessment.pdf");
try {
OutputStream out = new FileOutputStream(FileUtils.getAbsoluteFile(fileName));
PdfUtil pdf = new PdfUtil();
pdf.fillTemplate(mapJson ,out,templateFileName);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return AjaxResult.success(fileName);
}
具体导出结果
完美收官!!!!撒花~~
加个后续:
使用过程中发现有中文字段缺失的情况,比如应该导出“我爱我的祖国”的字符串,但在实际中只导出了“我爱祖国” 类似这样的情况,解决方法如下:
BaseFont bf =BaseFont.createFont("STSong-Light", "UniGB-UCS2-H",BaseFont.NOT_EMBEDDED);
Font f = new Font(bf,12,Font.NORMAL);
form.addSubstitutionFont(bf);
这次真的完美收官!!!