介绍

本篇博客主要是为了介绍如何使用:flying-saucer+itext+freemark实现导出复杂点的pdf文件。

思路

  • 先把pdf的内容以html形式准备好
  • 使用freemarker将html中的动态内容替换掉
  • 使用flying-saucer生成pdf文件

下载jar包

<dependency>
<groupId>org.xhtmlrenderer</groupId>
<artifactId>flying-saucer-pdf</artifactId>
<version>9.1.5</version>
</dependency>

下载中文字体

搜索:simsun.ttc

宋体(对应css中的 属性 font-family: SimSun; /宋体/)

准备好pdf的模板

把这个模板放到

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html
PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<title>准考证</title>
<style>
@page { size: 13.8in 10.4in; }
</style>
<!--@page { size: 13.8in 10.4in; } 这个可以调整pdf页面的大小很好用-->
</head>
<body>
<div style="width: 1200px; margin:0 auto; background: #fff; position: relative">
<img src="/isuyang/images/steam/students.jpg" width="1200px;" alt=""/>
<span style="color:#333; font-size:12.0pt; font-family: ; position: absolute; top: 63px; left:154px;">${certificateNumber}</span>
<span style="color:#333; font-size:20.0pt; font-family: SimSun; font-weight: bold; position: absolute; top: 320px; left:236px;width: 160px; text-align: center">${realName}</span>
<span style="color:#333; font-size:20.0pt; font-family: SimSun; font-weight: bold; position: absolute; top: 426px; left:236px;width: 140px; text-align: center">${division}</span>
<span style="color:#333; font-size:20.0pt; font-family: SimSun; font-weight: bold; position: absolute; top: 426px; left:428px;width: 140px; text-align: center">${grade}</span> <span style="color:#333; font-size:20.0pt; font-family: SimSun; font-weight: bold; position: absolute; top: 426px; left:612px;width: 140px; text-align: center">${prize}</span>
</div>
</body>
</html>

配置Freemaker

添加引用

<dependency>
<groupId>org.freemarker</groupId>
<artifactId>freemarker</artifactId>
<version>2.3.20</version>
</dependency>

在src/main/resource目录下创建ftl.properties文件

这个文件不一定非得放在这里,只是maven项目约定资源文件的目录是在这。

ftl的文件内容:

classic_compatible=true
##如果变量为null,转化为空字符串,比如做比较的时候按照空字符做比较
whitespace_stripping=true
##去掉多余的空格,非常有用
##模版更新事件,设置为1秒,正式环境设置为3600秒
#template_update_delay=3600
template_update_delay=1
##模版更新时间,这里配置是1秒更新一次,正式环境,模版不会改变,可以将这个值设很大,提高效率
##locale=zh_CN
##中国
default_encoding=utf-8
##编码utf8
url_escaping_charset=utf-8
##url编码utf8
date_format=yyyy-MM-dd
##显示日期格式
time_format=HH:mm:ss
##显示时间格式
datetime_format=yyyy-MM-dd HH:mm:ss
##显示日期格式
number_format=0.######
##数字显示格式
boolean_format=是,否
## boolean显示格式
tag_syntax=auto_detect
##设置标签类型 两种:[] 和 <> 。[] 这种标记解析要快些

在ftl.xml文件里配置freemarker.template.Configuration

记得在spring-context.xml文件里引用这个文件,

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.1.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.1.xsd"
default-lazy-init="true"> <description>ftl Configuration</description> <!-- 加载配置属性文件 -->
<context:property-placeholder ignore-unresolvable="true" location="classpath:config/config.properties" /> <bean id="configuration" class="freemarker.template.Configuration"/> </beans>

在启动的时候加载配置

/**
* 启动
* <p>
* 应用的启动入口
*
* @author ZhuangJunxiang(529272571@qq.com)
* @Date 2017年4月10日
*/
@Component
public class Setup implements ServletContextAware { @Override
public void setServletContext(final ServletContext context) {
WebApplicationContext act = ContextLoader.getCurrentWebApplicationContext();
Configuration ftlConf = (Configuration) act.getBean("configuration");
FtlUtil.initConfiguration(ftlConf, context, "/", "config/ftl.properties");
}
}

编写Controller

    /**
* 下载初赛的pdf证书
*
*/
@Void //这个是自定义注解,可以删除
@RequestMapping
@ResponseBody
public void downloadChuSaiPrizePdf() {
stemViewService.downloadPdf();
}

编写steamViewService

   public void downloadPdf() {
String pdfPath = generatorPdf(getSteamSignup(), "student.ftl");
boolean exist = FileUtil.isExist(pdfPath);
if (!exist) {
throw ExceptionUtil.bEx("PDF不存在");
}
try {
DownloadUtil.download(MvcUtil.getResponse(), pdfPath);
} catch (Exception e) {
e.printStackTrace();
} finally {
FileUtil.deleteFile(pdfPath);
}
}
/**
* 生成pdf
*
* @param parameter
* @return TODO(这里描述每个参数,如果有返回值描述返回值,如果有异常描述异常)
*/
public String generatorPdf(Map<String, Object> parameter, String ftlPath) {
//Pdf的存放路径:"G:\\pdf\\" 这里的路径我是通过配置获取的
String pdfPath = pdfConfig.getValue("pdfPath") + parameter.get("certificateNumber") + ".pdf";
//字体的存放路径 这里也是通过配置获取的:可以写:G:\\pdf\\simsun.ttc
String font1 = pdfConfig.getValue("fontPath"); OutputStream os = null;
try { os = new FileOutputStream(pdfPath);
ITextRenderer renderer = new ITextRenderer();
ResourceLoaderUserAgent callback = new ResourceLoaderUserAgent(renderer.getOutputDevice()); renderer.getSharedContext().setUserAgentCallback(callback);
callback.setSharedContext(renderer.getSharedContext());
//添加中文字体
renderer.getFontResolver().addFont(font1, BaseFont.IDENTITY_H, BaseFont.NOT_EMBEDDED);
//这里的ftl路径存放在WEB-INF/steam/下
String repAfterHtml = FtlUtil.build(configuration, "steam/" + ftlPath, parameter);
renderer.setDocumentFromString(repAfterHtml);
// 解决图片的相对路径问题,这里也可以写:http://localhost:8080/的形式
renderer.getSharedContext().setBaseURL("http://static.isuyang.cn/");
renderer.layout();
renderer.createPDF(os);
os.close();
os = null;
} catch (Exception ex) {
ex.printStackTrace();
} finally {
if (os != null) {
try {
os.close();
} catch (IOException e) {
// ignore
}
}
}
return pdfPath;
}
/**
* 资源加载代理
*
*/
private static class ResourceLoaderUserAgent extends ITextUserAgent {
public ResourceLoaderUserAgent(ITextOutputDevice outputDevice) {
super(outputDevice);
} protected InputStream resolveAndOpenStream(String uri) {
InputStream is = super.resolveAndOpenStream(uri);
System.out.println("加载资源文件: " + uri);
return is;
}
}

DownloadUtil.java

package com.we.core.web.util;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream; import javax.servlet.http.HttpServletResponse; import com.we.core.common.util.ExceptionUtil;
import com.we.core.common.util.FileUtil; /**
* 下载方法
* @author lq
* @Date 2014-7-15
*/
public class DownloadUtil { public static HttpServletResponse download(final HttpServletResponse response, final String path) throws Exception {
return download(response, path, null);
} public static HttpServletResponse download(final HttpServletResponse response, final String path,
final String fileName) throws Exception {
File file = new File(path);
String fn = fileName;
if (com.we.core.common.util.Util.isEmpty(fileName)) {
fn = file.getName();
} else {
if (fileName.indexOf(".") == -1) {
fn = fileName + "." + FileUtil.getSuffix(file.getName());
}
}
InputStream fis = new BufferedInputStream(new FileInputStream(path));
byte[] buffer = new byte[fis.available()];
fis.read(buffer);
fis.close();
response.reset();
response.addHeader("Content-Disposition", "attachment;filename="
+ new String(fn.getBytes("gb2312"), "ISO8859-1"));
response.addHeader("Content-Length", "" + file.length());
OutputStream toClient = new BufferedOutputStream(response.getOutputStream());
response.setContentType("application/octet-stream");
toClient.write(buffer);
toClient.flush();
toClient.close();
return response;
} public static HttpServletResponse viewWord(final HttpServletResponse response, final String path) throws Exception {
try {
File file = new File(path);
String filename = file.getName();
InputStream fis = new BufferedInputStream(new FileInputStream(path));
byte[] buffer = new byte[fis.available()];
fis.read(buffer);
fis.close();
response.reset();
response.addHeader("Content-Disposition", "inline;filename="
+ new String(filename.getBytes("gb2312"), "ISO8859-1"));
OutputStream toClient = new BufferedOutputStream(response.getOutputStream());
response.setContentType("application/pdf");
toClient.write(buffer);
toClient.flush();
toClient.close();
} catch (Exception e) {
throw ExceptionUtil.bEx("文件损坏,预览失败");
}
return response;
} public HttpServletResponse viewTxt(final HttpServletResponse response, final String path) throws Exception {
try {
BufferedReader bis = null;
File file = new File(path);
InputStream in = new FileInputStream(file);
bis = new BufferedReader(new InputStreamReader(in));
StringBuffer buf = new StringBuffer();
String temp;
while ((temp = bis.readLine()) != null) {
buf.append(temp);
response.getWriter().write(temp);
if (buf.length() >= 1000) {
break;
}
}
bis.close();
} catch (Exception e) {
throw ExceptionUtil.bEx("文件损坏,预览失败");
}
return response;
}
}

效果

建议

最好参考官方文档,因为好多写的都是不全,还有就是在搜索百度的时候一定要搜索博客靠前的文章,可以使用百度的搜索工具过滤一下。

https://developers.itextpdf.com/examples/xml-worker-itext5/html-images

java生成pdf的更多相关文章

  1. Java 生成pdf表格文档

    最近在工作做一个泰国的项目,应供应商要求,需要将每天的交易生成pdf格式的报表上传到供应商的服务器,特此记录实现方法.废话不多说,直接上代码: THSarabunNew.ttf该文件是泰国字体自行网上 ...

  2. JAVA生成PDF文件

    生成PDF文件是主要应用的是ITEXT插件 import java.awt.Color; import java.io.File; import java.io.FileOutputStream; i ...

  3. JAVA 生成PDF报表()

    许多应用程序都要求动态生成 PDF 文档.这些应用程序涵盖从生成客户对帐单并通过电子邮件交付的银行到购买特定的图书章节并以 PDF 格式接收这些图书章节的读者.这个列表不胜枚举.在本文中,我们将使用 ...

  4. Java生成PDF报表

    一.前言 前几天,做ASN条码收货模块,需要实现打印下载收货报表,经一番查找,选定iText--用于生成PDF文档的一个Java类库.废话不多说,进入正题. 二.iText简介 iText是著名的开放 ...

  5. java生成PDF文件(itext)

    itextpdf-5.4.3.jar下载地址: http://www.kuaipan.cn/file/id_58980483773788178.htm 导入itextpdf-5.4.3.jar ToP ...

  6. 电子凭证 : Java 生成 Pdf

    来源:蛙牛, my.oschina.net/lujianing/blog/894365 如有好文章投稿,请点击 → 这里了解详情 1.背景 在某些业务场景中,需要提供相关的电子凭证,比如网银/支付宝中 ...

  7. java生成PDF,各种格式、样式、水印都有

    代码中有两处需要图片,请自行替换. 一个是水印.一个是手指. 需要的JAR包链接:http://download.csdn.net/detail/justinytsoft/9688893 下面是预览: ...

  8. java生成PDF,并下载到本地

    1.首先要写一个PDF工具类,以及相关工具 2.PDF所需jar包 iText是一种生成PDF报表的Java组件 freemarker是基于模板来生成文本输出 <dependency> & ...

  9. Java生成PDF文件(转)

    原文地址:https://www.cnblogs.com/shuilangyizu/p/5760928.html 一.前言 前几天,做ASN条码收货模块,需要实现打印下载收货报表,经一番查找,选定iT ...

随机推荐

  1. 【Webpack】学习随笔

    参考链接:http://www.runoob.com/w3cnote/webpack-tutorial.html Webpack 是一个前端资源加载/打包工具. Webpack 可以将多种静态资源 j ...

  2. [Python 多线程] Condition (十)

    Condition常用于生产者.消费者模型,为了解决生产者消费者速度匹配问题. 构造方法Condition(lock=None),可以传入一个Lock或RLock对象,默认RLock. 方法: acq ...

  3. 20165302 学习基础和C语言基础调查

    学习基础和C语言基础调查 ====== 一,技能学习经验体会 要问我有什么技能比大多数人强,这个我还真的不敢说,虽然我在很多方面都有自己的一些了解,比如乐器和绘画,但也都是一知半解,并没有在某一方面出 ...

  4. PHP扩展功能 ---- 页面静态化(OB缓冲)

    一.入门三部曲 1.什么是页面静态化 百度百科介绍: 静态页面是网页的代码都在页面中,不需要执行asp,php,jsp,.net等程序生成客户端网页代码的网页,静态页面网址中一般不含"?&q ...

  5. Linux Ubuntu安装sogou中文输入法

    在linux下开发,有时还是需要使用中文输入法的,每次安装的时候都觉得痛苦,这次做下记录,方便下次安装. 安装fcitx 安装sogou输入法之前,需要安装fcitx(Free Chinese Inp ...

  6. [TJOI]2013 最长上升子序列

    这个题据说是Splay,或者说是平衡树的模板题,但是我还是不会做--唉-- \(\color{red}{Description}\) 给定一个序列,初始为空.现在我们将\(1\)到\(N\)的数字插入 ...

  7. Loadrunner上传文件与下载文件脚本

    Loadrunner上传文件与下载文件脚本 一. 上传脚本 Action() { int uploadImgStatus = 0; //获取上传产品图ID web_reg_save_param_ex( ...

  8. Android App的签名打包(晋级篇)

    http://blog.csdn.net/linghu_java/article/details/6701666 Andriod应用程序如果要在手机或模拟器上安装,必须要有签名! 1.签名的意义 为了 ...

  9. 创建DBLink----Oracle和mysql

    Oracle: DROP PUBLIC DATABASE LINK NM_HN; CREATE PUBLIC DATABASE LINK NM_HN CONNECT TO XZXT IDENTIFIE ...

  10. Linux下gdb调试(tui)

    1 处于TUI模式的GDB 为了以TUI模式运行GDB,可以在调用GDB时在命令行上指定-tui选项,或者处于非TUI模式时在GDB中使用Ctrl+X+A组合键.如果当前处于TUI模式,后一种命令方式 ...