1、背景
springboot 、 itext 、做好的pdf模板
2、代码
1、添加依赖
<!-- https://mvnrepository.com/artifact/com.itextpdf/itextpdf -->
<dependency>
<groupId>com.itextpdf</groupId>
<artifactId>itextpdf</artifactId>
<version>5.5.10</version>
</dependency>
<!-- https://mvnrepository.com/artifact/com.itextpdf/itext-asian -->
<dependency>
<groupId>com.itextpdf</groupId>
<artifactId>itext-asian</artifactId>
<version>5.2.0</version>
</dependency>
1、业务层代码
@Override
public File exportReport(String floodForecastingResultId) {
String newPdfPath = "C:/report.pdf";
PdfReader reader;
FileOutputStream out;
ByteArrayOutputStream bos;
PdfStamper stamper;
try{
File templateFile = ResourceUtils.getFile("classpath:templates/flood1.pdf");
String templatePath = templateFile.getPath();
out = new FileOutputStream(newPdfPath);
reader = new PdfReader(templatePath);// 读取pdf模板
bos = new ByteArrayOutputStream();
stamper = new PdfStamper(reader, bos);
AcroFields form = stamper.getAcroFields();
//设置显示中文
BaseFont bf = BaseFont.createFont("STSong-Light", "UniGB-UCS2-H", BaseFont.NOT_EMBEDDED);
ArrayList<BaseFont> fontList = new ArrayList<BaseFont>();
fontList.add(bf);
form.setSubstitutionFonts(fontList);
//处理数据
WaterForecastRecord waterForecastRecord = waterForecastRecordMapper.selectByRecordId(floodForecastingResultId);
//String[] str = { "03", "24", "08", "晴", "5", "6", "7", "8", "9","10","11","12","03","24","08","03","24","08","19","20","21","22","23"};
String[] content = getContentData(waterForecastRecord);
//String content[] = {"测试","测试","测试","测试","测试","测试","测试","测试","测试","测试","测试","测试","测试","测试","测试","测试","测试","测试","测试","测试","测试","测试","测试","测试","测试","测试","测试","测试","测试"};
int i = 0;
java.util.Iterator<String> it = form.getFields().keySet().iterator();
while (it.hasNext()) {
String name = it.next().toString();
form.setField(name, content[i++]);
}
stamper.setFormFlattening(true);// 如果为false那么生成的PDF文件还能编辑,一定要设为true
stamper.close();
Document doc = new Document();
PdfCopy copy = new PdfCopy(doc, out);
doc.open();
PdfImportedPage importPage = copy.getImportedPage(new PdfReader(bos.toByteArray()), 1);
copy.addPage(importPage);
doc.close();
//System.out.println("文件生成成功");
return new File(newPdfPath);
}catch (Exception e){
e.printStackTrace();
return null;
}
}
说明:floodForecastingResultId为一条记录的id,可以通过这个id 获取数据(由前端传过来),当然,自己造数据也是可以的,
比如上述代码中被注释的“测试”,中文显示不出来的问题代码中也有注释,添加上面相关代码就行,在这个方法中我是根据模板
生成了一个文件返回给控制层 ,由控制层去下载这个文件。
2、控制层代码(文件的下载)
@ApiOperation(value = "导出洪水预报成果pdf",httpMethod = "GET")
@GetMapping("/export")
public CommonResult exportPdf(@RequestParam("floodForecastingResultId") String floodForecastingResultId, HttpServletResponse response){
CommonResult result = ControllerUtil.judgeParamIsNull(floodForecastingResultId);
if(!Strings.isNullOrEmpty(result.getMessage())){
return result;
}
File file = waterForecastRecordService.exportReport(floodForecastingResultId);
String fileName = "洪水预报成果记录表.pdf";
try {
fileName = java.net.URLEncoder.encode(fileName, "utf-8");// IE11 浏览器
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
response.setContentType("application/force-download");// 设置强制下载不打开
response.addHeader("Content-Disposition", "attachment;fileName=" + fileName);// 设置文件名
byte[] buffer = new byte[1024];
FileInputStream fis = null;
BufferedInputStream bis = null;
try {
fis = new FileInputStream(file);
bis = new BufferedInputStream(fis);
OutputStream os = response.getOutputStream();
int i = bis.read(buffer);
while (i != -1) {
os.write(buffer, 0, i);
i = bis.read(buffer);
}
} catch (Exception e) {
e.printStackTrace();
} finally {
if (bis != null) {
try {
bis.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (fis != null) {
try {
fis.close();
} catch (IOException e) {
e.printStackTrace();
}
}
file.delete();
}
result.setCode(1);
result.setMessage("导出成功");
result.setObject(null);
return result;
}
3、碰到的问题
1、填充到模板中的中文字符串显示不出来
添加下面代码,这个代码在业务层也有,加到对应的地方就行(参照业务层代码)
//设置显示中文
BaseFont bf = BaseFont.createFont("STSong-Light", "UniGB-UCS2-H", BaseFont.NOT_EMBEDDED);
ArrayList<BaseFont> fontList = new ArrayList<BaseFont>();
fontList.add(bf);
form.setSubstitutionFonts(fontList);
2、模板的制作
用word 制作成表格,在转pdf ,在生成的pdf中编辑表单(不同的pdf 编辑器可能不一样),编辑表单后会有很多框,这个就是填充数据的地方,这个框编辑表单的时候是会自动生成些的,但用自动生成的会有很多问题,最好还是自己添加文字域,并设置字体大小、字体 ,和对齐方式(都在属性设置里面),字体和对齐方式不设置的话都会有一个默认值,具体的可以测试下,还有一个问题就是“m³” 在宋体的字体下,上标3显示不出来,而且导入的数字字体比较粗,经过多次测试“Calibri light”这个字体下数字还是比较细的没有那么粗 “m³”也能显示出来。文字域一定要自己手动添加,一定要自己手动添加,不然问题多多。