java导出PDF文件(插入图片,表格,字体)
业务需求:需要根据系统里的各种数据动态生成PDF会议材料。
最终呈现图
思路
因为会议材料涉及各种数据,图片。同时还要有表格及字体样式的要求,所以需要用每一页要用对应的模板来生成PDF.
所以第一步:用HTML页面绘制出每页的样式,然后改后缀将”.html“,换成”.ftl“,这样就完成FTL模板的转换,这里要注意的是,CSS样式的版本,因为后面我们要用freemark语法将数据写入到ftl模板中,而freemark语法有很多不支持高版本的CSS样式。所以最好用CSS低版本的。可以多试试。
第二步:freemark语法将数据写入到ftl模板中生成html页面。这里注意的是图片的插入和字体样式(代码中可以自己看)
第三步:将所有生成的html页面转换成PDF。
第四步:将所有生成的PDF合成一个PDF文件
注意:1、不用担心PDF文件中每页的顺序问题,这个是根据你的ftl模板的读取顺序来的。
2、这个html文件转PDF时候是不会自动换行的。这个网上有很多材料可以自己查,简单来说就是这个jar包是外国人开发的,支持英文空格换行。所以中文换行的话需要自己写方法。或者改JAR包,我水平不够,所以自己写方法实现的,就是有些麻烦,代码块中有。
资源目录
这里需要建一个资源目录,存放你的图片 和字体以及模板文件
字体,这俩个是黑体和宋体
模板文件(模板的文件名要和代码里面对应)
图片(PDF背景图也放这)
JAR包,这里需要itex5的jar包
你可以自己下,百度搜,这里就不多加赘述了
下面就代码部分
第一个class是业务部分,
package com.ttc.pdf;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.UUID;
import org.apache.commons.io.output.FileWriterWithEncoding;
import org.xhtmlrenderer.pdf.ITextFontResolver;
import org.xhtmlrenderer.pdf.ITextRenderer;
import com.itextpdf.text.Document;
import com.itextpdf.text.DocumentException;
import com.itextpdf.text.pdf.BaseFont;
import com.itextpdf.text.pdf.PdfCopy;
import com.itextpdf.text.pdf.PdfImportedPage;
import com.itextpdf.text.pdf.PdfReader;
import freemarker.template.Configuration;
import freemarker.template.Template;
public class Atest {
// 统计 生成html 页数
public final static ThreadLocal<Integer> pageNum = new ThreadLocal<Integer>();
public void exportResPdfSrv() {
// 初始值为0
pageNum.set(0);
try {
// 本地测试路径 请勿提交
String destFileName = "D:\\fbPDFRES";
String temporaryPath = destFileName + "\\fbFtl\\";// 获取ftl模板路径 和html及pdf临时生成文件路径
String imgPath = destFileName + "\\fbImgs\\";// 获取图片路径
String fontPath = destFileName + "\\fbFont\\";// 获取字体路径
String pdfPath = destFileName + "\\savePath\\";// 保存路径
// 删除目录下所有非后缀名为 ftl文件
this.deleteFiles(temporaryPath, FbExportPDFUtils.PDF_FTL);
// 生成pdf
this.createAllHTML(temporaryPath);
// 获取目录下所有html文件路径
List<String> htmlFiles = getFiles(temporaryPath, FbExportPDFUtils.PDF_HTML);
for (int i = 0; i < htmlFiles.size(); i++) {
String num = htmlFiles.get(i).substring(htmlFiles.get(i).indexOf("-") + 1,
htmlFiles.get(i).indexOf("."));
String PdfFileName = temporaryPath + UUID.randomUUID().toString().replace("-", "").toLowerCase() + "-"
+ num + FbExportPDFUtils.PDF_PDF;
// 生成pdf文件
prodPdfByHtmlNext(PdfFileName, htmlFiles.get(i), imgPath, fontPath);
}
// 获取目录下所有pdf文件路径
List<String> pdfFiles = getFiles(temporaryPath, "pdf");
SimpleDateFormat sdf = new SimpleDateFormat("MMddHHmmss");
// 物理子系统系统中文名称(英文简称)
String cname = "支付结算系统";
// 日期(年月日)_工单号+**系统汇报材料
String savePath = pdfPath + sdf.format(new Date()) + cname + FbExportPDFUtils.PDF_PDF;
// 合成pdf
this.morePdfToPdf(pdfFiles, savePath);
// 删除目录下所有非后缀名为 ftl文件
this.deleteFiles(temporaryPath, FbExportPDFUtils.PDF_FTL);
} catch (Exception e) {
System.out.print("PDF导出异常:" + e);
e.printStackTrace();
}
}
/**
* 生成所有PDF
*
* @param srPo
* @param temporaryPath
*/
private void createAllHTML(String temporaryPath) {
try {
// 生成第一页html
Map<String, Object> mapOneData = this.getOnePaddingData();
this.exportFtlToHtml(mapOneData, FbExportPDFUtils.PDF_ONE_PAGE, temporaryPath);
// 生成第二页html
Map<String, Object> maptwoData = new HashMap<String, Object>();
maptwoData.put("fbPageNumbers", 2);
this.exportFtlToHtml(maptwoData, FbExportPDFUtils.PDF_TWO_PAGE, temporaryPath);
// 生成第三页html
Map<String, Object> mapThreeData = this.getThreePaddingData();
this.exportFtlToHtml(mapThreeData, FbExportPDFUtils.PDF_THREE_PAGE, temporaryPath);
// 生成第四页html
Map<String, Object> mapFourData = this.getFourPaddingData();
this.exportFtlToHtml(mapFourData, FbExportPDFUtils.PDF_FOUR_PAGE, temporaryPath);
// 生成第五页html
Map<String, Object>