前言:

尝试了不少通过模板文件导出pdf文件的方法,要么实现起来复杂,要么实现效果不理想,经过反复查找资料和尝试发现此方法是最理想的。

本博客又经大量网友实践及建议,经过几次完善修改,又日趋完善,在此表示感谢。

一,依赖jar包

<!-- freemarker 读取html模板文件 -->
<dependency><groupId>org.freemarker</groupId><artifactId>freemarker</artifactId><version>2.3.23</version>
</dependency>
<!-- xml 将html模板文件转换成pdf -->
<dependency>    <groupId>org.xhtmlrenderer</groupId><artifactId>flying-saucer-pdf</artifactId><version>9.0.9</version>
</dependency>

二,模板文件(为html,命名后缀为.ftl)


SIMSUN.TTC文件来自自己计算机C:\WINDOWS\Fonts文件夹里面的宋体

注:这里的文件名是小写的,代码中是大写的,要保持一致,要么修改文件名为全部大写,要么修改代码中的文件名为小写。
pdf测试模板.ftl内容:

<!DOCTYPE html>
<html><head><meta charset="utf-8"/><title></title><style>*{margin: 0;padding: 0;box-sizing: border-box;}body{font-family: SimSun;}section{display:block;margin: 20px 10px;}.title{text-align: center;}.preface p{line-height: 30px;}.preface p.content{text-indent: 2em;}section > table{table-layout: fixed;width: 100%;margin: 20px 0px;text-align:center;word-wrap:break-word;}section table td{padding:5px 0px;}</style></head><body><!-- 标题 start --><section class="title"><h2>某报告</h2></section><!-- 标题 end --><!-- 前言 start --><section class="preface"><p>尊敬的用户:</p><p class="content">内容内容内容内容内容内容内容内容内容内容内容内容内容内容内容内容内容内容内容内容内容</p></section><!-- 前言 end --><!-- 汇总统计信息 start --><section class="count-info"><h4>汇总统计信息</h4><table border="1" cellspacing="0" cellpadding="0"><tr><td>本月笔数</td><td>近三个月数量对比</td></tr><tr><td>${curr}</td><td><table width="80%" border="1" cellspacing="0" cellpadding="0"style="margin: 5px auto;"><tr><td>${one}</td><td>${two}</td><td>${three}</td></tr></table></td></tr></table></section><!-- 汇总统计信息 end --><!-- 明细 start --><section class="detail"><h4>明细</h4><table border="1" cellspacing="0" cellpadding="0"><tr><td width="5%">序号</td><td width="15%">列1</td><td width="12%">列2</td><td width="12%">列3</td><td width="12%">列4</td><td>列5</td></tr><#list detailList as ad><tr><td>${ad_index+1}</td><td>${ad.column1}</td><td>${ad.column2}</td><td>${ad.column3}</td><td>${ad.column4}</td><td>${ad.column5}</td></tr></#list></table></section><!-- 明细 end --></body>
</html>

三,工具类实现

package test.pdf;import java.io.ByteArrayOutputStream;
import java.io.OutputStream;
import java.io.StringWriter;
import java.util.Locale;
import java.util.Map;
import org.xhtmlrenderer.pdf.ITextRenderer;
import com.lowagie.text.pdf.BaseFont;
import freemarker.template.Configuration;
import freemarker.template.Template;public class PDFTemplateUtil {/*** 通过模板导出pdf文件* @param data 数据* @param templateFileName 模板文件名* @throws Exception*/public static ByteArrayOutputStream createPDF(Map<String,Object> data, String templateFileName) throws Exception {// 创建一个FreeMarker实例, 负责管理FreeMarker模板的Configuration实例Configuration cfg = new Configuration(Configuration.DEFAULT_INCOMPATIBLE_IMPROVEMENTS);// 指定FreeMarker模板文件的位置cfg.setClassForTemplateLoading(PDFTemplateUtil.class,"/templates");ITextRenderer renderer = new ITextRenderer();OutputStream out = new ByteArrayOutputStream();try {// 设置 css中 的字体样式(暂时仅支持宋体和黑体) 必须,不然中文不显示renderer.getFontResolver().addFont("/templates/font/SIMSUN.TTC", BaseFont.IDENTITY_H, BaseFont.NOT_EMBEDDED);// 设置模板的编码格式cfg.setEncoding(Locale.CHINA, "UTF-8");// 获取模板文件Template template = cfg.getTemplate(templateFileName, "UTF-8");StringWriter writer = new StringWriter();// 将数据输出到html中template.process(data, writer);writer.flush();String html = writer.toString();// 把html代码传入渲染器中renderer.setDocumentFromString(html);// 设置模板中的图片路径 (这里的images在resources目录下) 模板中img标签src路径需要相对路径加图片名 如<img src="data:images/xh.jpg"/>String url = PDFTemplateUtil.class.getClassLoader().getResource("images").toURI().toString();renderer.getSharedContext().setBaseURL(url);renderer.layout();renderer.createPDF(out, false);renderer.finishPDF();out.flush();return (ByteArrayOutputStream)out;} finally {if(out != null){out.close();}}}
}

注:SIMSUN.TTC为宋体,可在C:\Windows\Fonts中查找

四,控制类实现

package test.controller;import java.io.ByteArrayOutputStream;
import java.io.OutputStream;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.servlet.http.HttpServletResponse;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import test.domain.PDFDataTest;
import test.pdf.PDFTemplateUtil;@RestController
@RequestMapping("/pdf")
public class PdfController {@RequestMapping("/export")public void exportPdf(HttpServletResponse response) throws Exception{ByteArrayOutputStream baos = null;OutputStream out = null;try {// 模板中的数据,实际运用从数据库中查询Map<String,Object> data = new HashMap<>();data.put("curr", 1);data.put("one", 2);data.put("two", 1);data.put("three", 6);List<PDFDataTest> detailList = new ArrayList<>();detailList.add(new PDFDataTest(123456,"测试","测试","测试","测试"));detailList.add(new PDFDataTest(111111,"测试","测试","测试","测试"));detailList.add(new PDFDataTest(222222,"测试","测试","测试","测试"));data.put("detailList", detailList);baos = PDFTemplateUtil.createPDF(data, "pdf测试模板.ftl");;// 设置响应消息头,告诉浏览器当前响应是一个下载文件response.setContentType( "application/x-msdownload");// 告诉浏览器,当前响应数据要求用户干预保存到文件中,以及文件名是什么 如果文件名有中文,必须URL编码String fileName = URLEncoder.encode("月度报告.pdf", "UTF-8"); response.setHeader( "Content-Disposition", "attachment;filename=" + fileName);out = response.getOutputStream();baos.writeTo(out);baos.close();} catch (Exception e) {e.printStackTrace();throw new Exception("导出失败:" + e.getMessage());} finally{if(baos != null){baos.close();}if(out != null){out.close();}}}
}

注意:模板中占位符值不能为null

附:PDFDataTest类

package test.domain;public class PDFDataTest {private Integer column1;private String column2;private String column3;private String column4;private String column5;public PDFDataTest(Integer column1, String column2, String column3, String column4, String column5) {super();this.column1 = column1;this.column2 = column2;this.column3 = column3;this.column4 = column4;this.column5 = column5;}public Integer getColumn1() {return column1;}public void setColumn1(Integer column1) {this.column1 = column1;}public String getColumn2() {return column2;}public void setColumn2(String column2) {this.column2 = column2;}public String getColumn3() {return column3;}public void setColumn3(String column3) {this.column3 = column3;}public String getColumn4() {return column4;}public void setColumn4(String column4) {this.column4 = column4;}public String getColumn5() {return column5;}public void setColumn5(String column5) {this.column5 = column5;}}

五、实现效果

六、横向显示

在css文件中添加

@page {size: landscape;
}

纵向:portrait
横向:landscape

效果:
竖屏:

横屏:

更多关于打印设置可参考博客:css @page规则控制打印设置选项

Java使用Freemarker通过模板文件导出PDF文件、横向显示相关推荐

  1. java中freemarker使用ftl模版生成PDF文件

    说明 调用方法生成PDF时,使用的ftl模版,以及字体都是从jar中读取的,无需担心多节点部署 引用jar <dependency><groupId>org.freemarke ...

  2. 使用freemarker模板引擎导出word文件

    目录 第一步:创建Word模板 第二步:整理好数据,核对好数据要填充的位置 第三步:使用工具类生成word文件 工具类: 第一步:创建Word模板 创建需要的模板 另存为:单一网页文件 文件名最好改为 ...

  3. 使用java导出pdf文件

    使用java导出pdf文件 itext itext的使用 JasperReports JasperReports与itext的区别 Jaspersoft Studio 工具简介 Jaspersoft ...

  4. java批量导出pdf文件_java导出pdf文件

    项目中导出pdf文件,需要3个jar包iText-2.1.7.jar,iTextAsian.jar,ReportExprotPlug0.1.jar. ReportInfo info = new Rep ...

  5. java 使用itext导出PDF文件,中文不显示问题解决

    之前写的java 使用itext 导出pdf 发现有个问题,在今天使用的时候,发现一个问题,就是当单元格中写中文的时候,导出来的pdf中文不显示. java 使用itext导出PDF文件,图片文字左右 ...

  6. Java中导出pdf文件,pdf工具类demo

    最近在做导出pdf文件的功能,参考了很多资料和demo,完成了转出pdf的功能,并适合项目的pdf工具类,现贴出具体的工具类和demo,如有不对的地方欢迎指正 1.pdf工具类PdfUtil.java ...

  7. 咖啡汪日志——JAVA导出pdf文件加水印 文字+图片、文字

    咖啡汪日志--JAVA导出pdf文件加水印 文字和图片.文字 hello,又大家见面了! 作为一只不是在戏精就是在戏精路上的哈士奇,今天要展示给大家的就是如何快捷地给pdf文件增加各种水印.嗷呜呜,前 ...

  8. java使用world模板动态生成PDF文件

    根据项目需求,需要用到一个功能,根据页面参数需要动态的生成一个world,并将world生成两份PDF文件,一份正式文件,一份临时的电子文件(带有二维码,扫描可以下载正式文件的电子版本).同时上传到文 ...

  9. Freemark 模板生成doc文件,xml doc文件转docx 文件,docx文件转pdf文件

    freemark 模板生成doc文件,此doc文件为xml格式,无法直接转pdf 需要doc转docx文件,才能转pdf 方法1:docx4j 转 pdf 方法2: e-iceblue docx 转 ...

最新文章

  1. python开发效率最高_公认8个效率最高的爬虫框架
  2. GridCtrl学习笔记(2)寻找自动更新表格的最新数据并把其显示到当前窗口的方法...
  3. 做网页前端遇到的一些问题
  4. iOS 第三方登录之 QQ登录
  5. python学习list_python学习之list
  6. linux 制作yum,Linux制作本地yum
  7. 基础:某个应用的CPU使用率高达100%,该怎么处理
  8. css3循环360度图片旋转
  9. 1879: Intersection
  10. 关于AQS中自旋的理解
  11. 4-5 zookeeper四字命令
  12. 同质化游戏做出不同点在于背景音乐
  13. dd_engi的背包九讲(新版转载)
  14. 合成大西瓜——修改图片及发布详细教程
  15. unity 3d slider机械臂转动
  16. Java编辑工具——IDEA图标含义大全
  17. 相控阵天线(九):平面阵列天线综合(不可分离型切比雪夫分布、圆口径泰勒综合、可分离型分布、配相抵消法)
  18. 三国赵云传1---辅助研究
  19. Android系统和版本介绍
  20. Chrome 浏览器 强制清空缓存

热门文章

  1. java binary name
  2. vba 判断文本框内容是否为空_VBA代码解决方案第119讲:如何遍历工作表中的图形...
  3. pytest框架之fixture详细使用方法及举例
  4. imessage_如何防止某些人知道您已阅读他们的iMessage
  5. 微信搜索,给你不一样的微信!
  6. Python3.10升级记录
  7. 联发科mtk和骁龙730哪个好_天玑720和骁龙730G哪个好_天玑720和骁龙730G性能对比
  8. opencv安装 及 opencv安装过程遇到问题的解决方案
  9. hdoj_1196_Lowest Bit 树状数组基本思想
  10. MACD技术的高级应用--MACD与波浪