java根据模板导出_java根据模板导出PDF详细教程(完整版)详解

本文详述了如何利用iText、FreeMarker和JFreeChart在Java中根据模板生成动态配置的PDF文档,包括动态内容、字体配置、页眉页脚、图表生成等,并分享了遇到的问题及解决方案。
摘要由CSDN通过智能技术生成

题记:由于业务的需要,需要根据模板定制pdf文档,经测试根据模板导出word成功了;但是导出pdf相对麻烦了一点。两天的研究测试java导出PDF,终于成功了,期间走了不少弯路,今分享出来,欢迎大家有问题在此交流,与君共勉!

一、需求

根据业务需要,需要在服务器端生成可动态配置的PDF文档,方便数据可视化查看。

此文的测试是在客户端通过java程序的测试,直接运行java类获得成功!

二、解决方案

iText+FreeMarker+JFreeChart生成可动态配置的PDF文档。

iText有很强大的PDF处理能力,但是样式和排版不好控制,直接写PDF文档,数据的动态渲染很麻烦。

FreeMarker能配置动态的html模板,正好解决了样式、动态渲染和排版问题。

JFreeChart有这方便的画图API,能画出简单的折线、柱状和饼图,基本能满足需要。

三、实现功能

1、能动态配置PDF文档内容

2、能动态配置中文字体显示

3、设置自定义的页眉页脚信息

4、能动态生成业务图片

5、完成PDF的分页和图片的嵌入

四、主要代码结构说明:

1、component包:PDF生成的组件 对外提供的是PDFKit工具类和HeaderFooterBuilder接口,其中PDFKit负责PDF的生成,HeaderFooterBuilder负责自定义页眉页脚信息。

2、builder包:负责PDF模板之外的额外信息填写,这里主要是页眉页脚的定制。

3、chart包:JFreeChart的画图工具包,目前只有一个线形图。

4、test包:测试工具类

5、util包:FreeMarker等工具类。

项目采用maven架构,开发工具为MyEclipse10,环境为jdk1.7

五、关键代码说明

1、模板配置html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">

body {

font-family: pingfang sc light;

}

.center{

text-align: center;

width: 100%;

}

${templateName}

iText官网:${ITEXTUrl}

FreeMarker官网:${freeMarkerUrl}

JFreeChart教程:${JFreeChartUrl}

静态logo图

         

气温变化对比图

         

第二页开始了
列表值:

${item}

#list>

2、获取模板内容并填充数据public static String getContent(String fileName,Object data){

String templatePath=getPDFTemplatePath(fileName).replace("\\", "/");

String templateFileName=getTemplateName(templatePath).replace("\\", "/");

String templateFilePath=getTemplatePath(templatePath).replace("\\", "/");

System.out.println("templatePath:"+templatePath);

System.out.println("templateFileName:"+templateFileName);

System.out.println("templateFilePath:"+templateFilePath);

if(StringUtils.isEmpty(templatePath)){

throw new FreeMarkerException("templatePath can not be empty!");

}

try{System.out.println("进到这里了,有来无回1");

Configuration config = new Configuration(Configuration.VERSION_2_3_25);

config.setDefaultEncoding("UTF-8");

config.setDirectoryForTemplateLoading(new File(templateFilePath));

config.setTemplateExceptionHandler(TemplateExceptionHandler.RETHROW_HANDLER);

config.setLogTemplateExceptions(false);System.out.println("进到这里了,有来无回2");

Template template = config.getTemplate(templateFileName);System.out.println("进到这里了,有来无回3");

StringWriter writer = new StringWriter();

template.process(data, writer);

writer.flush();

String html = writer.toString();

return html;

}catch (Exception ex){

throw new FreeMarkerException("FreeMarkerUtil process fail",ex);

}

}

public static String getContent(String fileName,Object data){

String templatePath=getPDFTemplatePath(fileName);//根据PDF名称查找对应的模板名称

String templateFileName=getTemplateName(templatePath);

String templateFilePath=getTemplatePath(templatePath);

if(StringUtils.isEmpty(templatePath)){

throw new FreeMarkerException("templatePath can not be empty!");

}

try{

Configuration config = new Configuration(Configuration.VERSION_2_3_25);//FreeMarker配置

config.setDefaultEncoding("UTF-8");

config.setDirectoryForTemplateLoading(new File(templateFilePath));//注意这里是模板所在文件夹,不是文件

config.setTemplateExceptionHandler(TemplateExceptionHandler.RETHROW_HANDLER);

config.setLogTemplateExceptions(false);

Template template = config.getTemplate(templateFileName);//根据模板名称 获取对应模板

StringWriter writer = new StringWriter();

template.process(data, writer);//模板和数据的匹配

writer.flush();

String html = writer.toString();

return html;

}catch (Exception ex){

throw new FreeMarkerException("FreeMarkerUtil process fail",ex);

}

}

3、导出模板到PDF文件/**

* @description     导出pdf到文件

* @param fileName  输出PDF文件名

* @param data      模板所需要的数据

*

*/

public String exportToFile(String fileName,Object data){

try {

String htmlData= FreeMarkerUtil.getContent(fileName, data);

if(StringUtils.isEmpty(saveFilePath)){

saveFilePath=getDefaultSavePath(fileName);

}

File file=new File(saveFilePath);

if(!file.getParentFile().exists()){

file.getParentFile().mkdirs();

}

FileOutputStream outputStream=null;

try{

//设置输出路径

outputStream=new FileOutputStream(saveFilePath);

//设置文档大小

Document document = new Document(PageSize.A4);

PdfWriter writer = PdfWriter.getInstance(document, outputStream);

//设置页眉页脚

PDFBuilder builder = new PDFBuilder(headerFooterBuilder,data);

builder.setPresentFontSize(10);

writer.setPageEvent(builder);

//输出为PDF文件

convertToPDF(writer,document,htmlData);

}catch(Exception ex){

throw new PDFException("PDF export to File fail",ex);

}finally{

IOUtils.closeQuietly(outputStream);

}

} catch (Exception e) {

e.printStackTrace();

}

return saveFilePath;

}

4、测试工具类public  String createPDF(Object data, String fileName){

//pdf保存路径

try {

//设置自定义PDF页眉页脚工具类

PDFHeaderFooter headerFooter=new PDFHeaderFooter();

PDFKit kit=new PDFKit();

kit.setHeaderFooterBuilder(headerFooter);

//设置输出路径

kit.setSaveFilePath("D:/Users/hello.pdf");

String saveFilePath=kit.exportToFile(fileName,data);

return  saveFilePath;

} catch (Exception e) {

System.out.println("竟然失败了,艹!");

e.printStackTrace();

//            log.error("PDF生成失败{}", ExceptionUtils.getFullStackTrace(e));

log.error("PDF生成失败{}");

return null;

}

}

public static void main(String[] args) {

ReportKit360 kit=new ReportKit360();

TemplateBO templateBO=new TemplateBO();

templateBO.setTemplateName("Hello iText! Hello freemarker! Hello jFreeChart!");

templateBO.setFreeMarkerUrl("http:www.itxm.cn");

templateBO.setITEXTUrl("http://developers.itextpdf.com/examples-itext5");

templateBO.setJFreeChartUrl("http:www.itxm.cn");

templateBO.setImageUrl("E:/图片2/004d.jpg");

List scores=new ArrayList();

scores.add("94");

scores.add("95");

scores.add("98");

templateBO.setScores(scores);

List lineList=getTemperatureLineList();

DefaultLineChart lineChart=new DefaultLineChart();

lineChart.setHeight(500);

lineChart.setWidth(300);

String picUrl=lineChart.draw(lineList,0);

templateBO.setPicUrl(picUrl);System.out.println("picUrl:"+picUrl);

String path= kit.createPDF(templateBO,"hello.pdf");

System.out.println("打印:"+path);

}

此测试工具类中,要注意几点:

1)templateBO.setImageUrl("E:/图片2/004d.jpg");中的参数修改为自己本地有的图片;

2)程序可能会报找不到模板引擎hello.ftl文件的错误,一定要将源码中的hello.ftl放在本地硬盘对应的目录中;

六、生成结果

七、遇到的坑

1、FreeMarker配置模板文件样式,在实际PDF生成过程中,可能会出现一些不一致的情形,目前解决方法,就是换种方式调整样式。

2、字体文件放在resource下,在打包时会报错,运行mvn -X compile 会看到详细错误:

这是字体文件是二进制的,而maven项目中配置了资源文件的过滤,不能识别二进制文件导致的,plugins中增加下面这个配置就好了:

src/main/resources

true

org.apache.maven.plugins

maven-resources-plugin

2.7

UTF-8

ttf

3、PDF分页配置:

在ftl文件中,增加分页标签:

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
根据提供的引用内容,可以使用Java实现根据模板生成并导出PDF的功能。具体步骤如下: 1.使用JavaPDF库,例如iText或Apache PDFBox,读取PDF模板文件。 2.使用模板文件中的参数,填充PDF表单字段或者在PDF页面上添加文本、图片等内容。 3.将填充后的PDF文件导出到指定的路径。 下面是一个使用iText库实现根据模板导出PDF的示例代码: ```java import com.itextpdf.text.Document; import com.itextpdf.text.pdf.PdfCopy; import com.itextpdf.text.pdf.PdfImportedPage; import com.itextpdf.text.pdf.PdfReader; import com.itextpdf.text.pdf.PdfStamper; import java.io.FileOutputStream; import java.util.Map; public class PdfGenerator { public static void generatePdf(String templatePath, String outputPath, Map<String, String> params) throws Exception { // 读取PDF模板文件 PdfReader reader = new PdfReader(templatePath); // 创建输出流 FileOutputStream fos = new FileOutputStream(outputPath); // 创建PDF文档对象 Document document = new Document(); // 创建PDF写入器 PdfCopy copy = new PdfCopy(document, fos); // 打开文档 document.open(); // 填充PDF表单字段 PdfStamper stamper = new PdfStamper(reader, fos); for (Map.Entry<String, String> entry : params.entrySet()) { stamper.getAcroFields().setField(entry.getKey(), entry.getValue()); } stamper.setFormFlattening(true); stamper.close(); // 将填充后的PDF文件导出到指定的路径 for (int i = 1; i <= reader.getNumberOfPages(); i++) { PdfImportedPage page = copy.getImportedPage(new PdfReader(reader), i); copy.addPage(page); } document.close(); reader.close(); fos.close(); } } ``` 其中,`templatePath`为PDF模板文件的路径,`outputPath`为导出PDF文件的路径,`params`为填充PDF表单字段的参数。可以根据实际需求修改代码。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值