业务需求:
- 生成点击行的PDF,下载和预览功能
- 预览可选择PDF或者html原界面,下载必须时PDF
预览功能:
采用Freemarker技术,生成静态化界面
编写模板,获取模型数据,生成静态化页面,将页面转换成流返回前端展示
/*预览*/
function preview() {
window.open('你的后台路径'};
/*
* @Author Wu
* @Description //TODO 预览
* @Param [contracNo, model]
* @return java.lang.String
*/
@RequestMapping("/contractpreview")
public String contractPreview(Model model) {
//获取数据模型 根据合同号和当前登录人的UUID组合查询合同信息
Student stu = new Student();
stu.setName("张三");
model.addAttribute("model", stu);
return "template";
}
<!DOCTYPE html>
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8" %>
<head>
<meta charset="UTF-8">
<title>合同预览</title>
</head>
<body>
<p align="center" style='font-size:22px'>
${model.stu.name};
</p>
</body>
</html>
以上是获取模型数据,将数据返回给模板界面。 你也可以选择获取数据和模板文件,使用freemarker将界面静态化好,返回给前端一个文件流
PDF生成下载功能:
- 获取数据模型
- 或者模板文件
- 执行静态化,返回HTM界面字符串
- 将HTML界面字符串生成PDF文件
/*下载*/
function download(){
//同界面操作
window.location.href="下载的URL";
}
/*
* @Author Wu
* @Description //TODO 下载
* @Param [contracNo]
* @return org.springframework.http.ResponseEntity<byte[]>
*/
@RequestMapping("/download")
public ResponseEntity<byte[]> download(String contracNo) {
//声名一个存放生成好的PDF文件的路径
String str = this.getClass().getResource("/").getPath() + "template/";
HttpHeaders httpHeaders = new HttpHeaders();
//获取数据模型
Student stu = new Student();
stu.setName("张三");
//每次生成文件之前删除该路径下的.PDF文件,因为该文件不需要存储,只为了临时存储进行读取
if(!deleteSuffix(new File(str))){
//下载失败返回
httpHeaders.add("Content-Disposition","attachment;filename=error.log");
return new ResponseEntity<byte[]>(("文件删除失败,联系管理员,filename:"+ wm.getContractUuid() + ".pdf").getBytes(),httpHeaders,HttpStatus.OK);
}
String pdfName = str + "自己选择文件名" + ".pdf";
//避免异常,如果文件夹不存在,则创建
createFiles(str);
try {
//转换Map
Map<String, Object> stringObjectMap = beanToMap(stu );
//获取页面模板信息
InputStream resourceAsStream = getClass().getClassLoader().getResourceAsStream("template/template.html");
//文件内容ToString
String templateStr = IOUtils.toString(resourceAsStream, "utf-8");
//通过模板和模型生成静态化html并且传换字符串
String successHtmlStr = generateHtml(templateStr, stringObjectMap);
HtmlToPdfUtils.htmlStrToPdf(pdfName, successHtmlStr);
File filePdf = new File(pdfName);
httpHeaders.setContentDispositionFormData("attachment", java.net.URLEncoder.encode(filePdf.getName(), "UTF-8"));
httpHeaders.setContentType(MediaType.parseMediaType("application/pdf"));
return new ResponseEntity<byte[]>(FileUtils.readFileToByteArray(filePdf),
httpHeaders,
HttpStatus.CREATED);
} catch (Exception e) {
e.printStackTrace();
}
//下载失败返回
httpHeaders.add("Content-Disposition", "attachment;filename=error.log");
return new ResponseEntity<byte[]>(("文件下载失败,filename:" + wm.getContractUuid() + ".pdf").getBytes(), httpHeaders, HttpStatus.OK);
}
//执行静态化
private String generateHtml(String templateContent, Map contarct) {
//创建配置对象
Configuration configuration = new Configuration(Configuration.getVersion());
//创建模板加载器
StringTemplateLoader stringTemplateLoader = new StringTemplateLoader();
stringTemplateLoader.putTemplate("template", templateContent);
//向configuration配置模板加载器
configuration.setTemplateLoader(stringTemplateLoader);
try {
Template template = configuration.getTemplate("template");
//调用api进行静态化
String content = FreeMarkerTemplateUtils.processTemplateIntoString(template, contarct);
return content;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
//删除指定后缀名的文件
private static boolean deleteSuffix(File f) {
File[] fi=f.listFiles();
if(fi!=null){
for (File file : fi) {
if(file.isDirectory()){
deleteSuffix(file);
}else if(file.getName().substring(file.getName().lastIndexOf(".")+1).equals("pdf")){
System.out.println("成功删除"+file.getName());
file.delete();
}
return true;
}
return false;
}
return true;
}
public static String createFiles(String fileName) {
// String path = this.getClass().getResource("/").getPath();
File file = new File(fileName);
if (file.exists()) {
if (file.isDirectory()) {
System.out.println("dir exists");
return fileName;
} else {
System.out.println("the same name file exists, can not create dir");
return fileName;
}
} else {
System.out.println("dir not exists, create it ...");
file.mkdir();
return fileName;
}
}
生成PDF的工具类
public class HtmlToPdfUtils{
/**
* 根据html文件生成pdf
* @param pdfFilePath pdf文件生成路径
* @param htmlFilePath html文件路径
*/
public static void htmlFileToPdf(String pdfFilePath, String htmlFilePath) {
Document document = new Document();
PdfWriter writer = null;
FileOutputStream fileOutputStream = null;
FileInputStream fileInputStream = null;
try {
fileOutputStream = new FileOutputStream(pdfFilePath);
writer = PdfWriter.getInstance(document, fileOutputStream);
// 设置底部距离60,解决重叠问题
document.setPageSize(PageSize.A4);
document.setMargins(50, 45, 50, 60);
document.setMarginMirroring(false);
document.open();
StringBuffer sb = new StringBuffer();
fileInputStream = new FileInputStream(htmlFilePath);
BufferedReader br = new BufferedReader(new InputStreamReader(fileInputStream, "UTF-8"));
String readStr = "";
while ((readStr = br.readLine()) != null) {
sb.append(readStr);
}
XMLWorkerHelper.getInstance().parseXHtml(writer, document, new ByteArrayInputStream(sb.toString().getBytes("Utf-8")), null, Charset.forName("UTF-8"), new MyFontProvider("/template/simsun.ttc,0"));
} catch (Exception e) {
e.printStackTrace();
} finally {
if (null != document) {
document.close();
}
if (null != writer) {
writer.close();
}
if (null != fileInputStream) {
try {
fileInputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (null != fileOutputStream) {
try {
fileOutputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
/**
* 根据html字符串内容生成pdf
*
* @param pdfFilePath pdf文件存储位置
* @param htmlcontent html内容
*/
public static void htmlStrToPdf(String pdfFilePath, String htmlcontent) {
Document document = new Document();
PdfWriter writer = null;
try {
writer = PdfWriter.getInstance(document, new FileOutputStream(pdfFilePath));
// 设置底部距离60,解决重叠问题
document.setPageSize(PageSize.A4);
document.setMargins(50, 45, 50, 60);
document.setMarginMirroring(false);
document.open();
XMLWorkerHelper instance = XMLWorkerHelper.getInstance();
instance.parseXHtml(writer, document, new ByteArrayInputStream(htmlcontent.getBytes("UTF-8")), null, Charset.forName("UTF-8"), new MyFontProvider("/template/simsun.ttc,0"));
} catch (Exception e) {
e.printStackTrace();
} finally {
if (null != document) {
document.close();
}
if (null != writer) {
writer.close();
}
}
}
public static void main(String[] args) {
try {
// 本地
// String htmlFile = "C:\\test.html";
String pdfFile = "abc.pdf";
String htmlContent = "<html xmlns='http://www.w3.org/1999/xhtml'><head><meta charset='UTF-8'/><title>预览</title></head><body><p align='center' style='font-size:22px'>中文English</p><table width='100%' style='font-size:12px;'><tr width='100%'><td width='50%' align='left' valign='top'>ZXCZXCVXCV啊阿斯顿<br/></td></tr></table></body></html>";
htmlStrToPdf(pdfFile,htmlContent);
// htmlFileToPdf(pdfFile,htmlFile);
} catch (Exception e) {
e.printStackTrace();
}
}
}
字体类:
public class MyFontProvider extends XMLWorkerFontProvider {
private String fontPath;
public MyFontProvider(String filePath) {
this.fontPath = filePath;
}
@Override
public Font getFont(final String fontname, final String encoding, final boolean embedded, final float size, final int style, final BaseColor color) {
BaseFont bf = null;
try {
bf = BaseFont.createFont(fontPath, BaseFont.IDENTITY_H, BaseFont.NOT_EMBEDDED);
} catch (DocumentException | IOException e) {
e.printStackTrace();
}
Font font = new Font(bf, size, style, color);
font.setColor(color);
return font;
}
}
注意要下载字体文件simsun.ttc或者simsun.ttf
POM文件如下:
<!--静态化-->
<dependency>
<groupId>org.freemarker</groupId>
<artifactId>freemarker</artifactId>
<version>2.3.23</version>
</dependency>
<!--PDF-->
<dependency>
<groupId>org.xhtmlrenderer</groupId>
<artifactId>core-renderer</artifactId>
<version>R8</version>
</dependency>
<dependency>
<groupId>commons-codec</groupId>
<artifactId>commons-codec</artifactId>
</dependency>
<dependency>
<groupId>com.itextpdf</groupId>
<artifactId>itextpdf</artifactId>
<version>5.5.1</version>
</dependency>
<dependency>
<groupId>com.itextpdf.tool</groupId>
<artifactId>xmlworker</artifactId>
<version>5.5.9</version>
</dependency>