导出pdf的一种实现方式 freemark+itext
pdf由于不可编辑性,导出时不能像excel一样直接在模板上填充数据,因此需要在模板生成之前填充数据,下面的一种方式是利用html转pdf,freemark可以做html模板,itext生成pdf,能够解决基本的pdf导出需求。
首先根据自己的业务需求,做一个html模板,如下图所示:
往设定好html模板上填充数据:
List<ExportDomain> list = new ArrayList<ExportDomain>();
ExportDomain exportDomain = new ExportDomain();
exportDomain.setUserName("张三");
exportDomain.setRoleName("管理员");
exportDomain.setMenuName("功能1");
list.add(exportDomain);
ExportDomain exportDomain1 = new ExportDomain();
exportDomain1.setUserName("李四");
exportDomain1.setRoleName("办理员");
exportDomain1.setMenuName("功能2");
list.add(exportDomain1);
ExportDomain exportDomain2 = new ExportDomain();
exportDomain2.setUserName("王五");
exportDomain2.setRoleName("稽核员");
exportDomain2.setMenuName("功能3");
list.add(exportDomain2);
Map<String, Object> dataModel = new HashMap<String, Object>();
dataModel.put("title", "HTML转PDF测试");
dataModel.put("userList", list);
dataModel.put("reportDate", new SimpleDateFormat("yyyy-MM-dd").format(new Date()));
dataModel.put("reportUser", "大哥大");
File file = new File("E:/resource/aaa.png");
byte[] fileByte = Files.readAllBytes(file.toPath());
String s = new BASE64Encoder().encode(fileByte);
String img = "data:image/jpg;base64," + s;
dataModel.put("pic", img);
注:ExportDomain是业务需求的实体类。
使用freemark制作html模板,将数据写入html中:
Writer out = null;
StringReader reader = null;
try {
out = new StringWriter();
Configuration cfg = new Configuration();
cfg.setDefaultEncoding("UTF-8");
cfg.setDirectoryForTemplateLoading(new File("E:/resource"));
Template template = cfg.getTemplate(html);
template.process(dataModel, out);
reader = new StringReader(out.toString());
out.flush();
} catch (Exception e) {
e.printStackTrace();
throw e;
} finally {
if (out != null) {
out.close();
}
}
BufferedReader br = new BufferedReader(reader);
StringBuilder content = new StringBuilder();
String str = null;
while ((str = br.readLine()) != null) {
content.append(str);
}
使用itext将html转换为pdf流
ByteArrayOutputStream out = new ByteArrayOutputStream();
//设置文档大小
Document document = new Document(PageSize.A4);
PdfWriter writer = PdfWriter.getInstance(document, out);
//itext图片立即合成
writer.setStrictImageSequence(true);
//输出为PDF文件
document.open();
MyFontsProvider fontProvider = new MyFontsProvider();
fontProvider.addFontSubstitute("lowagie", "garamond");
fontProvider.setUseUnicode(true);
CssAppliers cssAppliers = new CssAppliersImpl(fontProvider);
CSSResolver cssResolver = XMLWorkerHelper.getInstance().getDefaultCssResolver(true);
// HTML
HtmlPipelineContext htmlContext = new HtmlPipelineContext(cssAppliers);
htmlContext.setTagFactory(Tags.getHtmlTagProcessorFactory());
htmlContext.setImageProvider(new AbstractImageProvider() {
@Override
public Image retrieve(String src) {
int pos = src.indexOf("base64,");
try {
if (src.startsWith("data") && pos > 0) {
byte[] img = Base64.decode(src.substring(pos + 7));
return Image.getInstance(img);
} else if (src.startsWith("http")) {
return Image.getInstance(src);
}
} catch (BadElementException ex) {
return null;
} catch (IOException ex) {
return null;
}
return null;
}
@Override
public String getImageRootPath() {
return null;
}
});
// Pipelines
PdfWriterPipeline pdf = new PdfWriterPipeline(document, writer);
HtmlPipeline html = new HtmlPipeline(htmlContext, pdf);
CssResolverPipeline css = new CssResolverPipeline(cssResolver, html);
// XML Worker
XMLWorker worker = new XMLWorker(css, true);
XMLParser p = new XMLParser(worker);
p.parse(new StringReader(htmlString));
document.close();
FileOutputStream输出pdf流,完成pdf下载,效果图:
好了,到这里pdf导出基本结束,附上可运行的源码。
下载地址:https://download.csdn.net/download/qq_29277699/11109421