场景:
将前端传入的值,直接插入指定的模板中,来生成pdf租房合同,生成的pdf样式,使用html页面来控制。
代码如下:
首先:
使用了velocity模板引擎技术来实现传值稳定插入到指定位置。
以上是html模板 ,要求html遵守xhtml的规范,严格语法要求。
然后下面是引用的maven坐标
<dependencies>
<!-- velocity依赖 -->
<dependency>
<groupId>org.apache.velocity</groupId>
<artifactId>velocity-engine-core</artifactId>
<version>2.3</version>
</dependency>
<dependency>
<groupId>org.apache.velocity.tools</groupId>
<artifactId>velocity-tools-generic</artifactId>
<version>3.1</version>
</dependency>
<dependency>
<groupId>org.apache.velocity.tools</groupId>
<artifactId>velocity-tools-view</artifactId>
<version>3.1</version>
</dependency>
<dependency>
<groupId>org.apache.velocity.tools</groupId>
<artifactId>velocity-tools-view-jsp</artifactId>
<version>3.0</version>
</dependency>
<!-- 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.1.8</version>
</dependency>
<dependency>
<groupId>com.itextpdf</groupId>
<artifactId>itextpdf</artifactId>
<version>5.5.11</version>
</dependency>
<dependency>
<groupId>com.itextpdf.tool</groupId>
<artifactId>xmlworker</artifactId>
<version>5.5.8</version>
</dependency>
<dependency>
<groupId>org.xhtmlrenderer</groupId>
<artifactId>flying-saucer-pdf</artifactId>
<version>9.0.3</version>
</dependency>
<dependency>
<groupId>com.itextpdf</groupId>
<artifactId>itext-asian</artifactId>
<version>5.2.0</version>
</dependency>
<dependency>
<groupId>com.itextpdf</groupId>
<artifactId>itext-pdfa</artifactId>
<version>5.5.8</version>
</dependency>
<dependency>
<groupId>org.apache.pdfbox</groupId>
<artifactId>pdfbox</artifactId>
<version>2.0.19</version>
</dependency>
<!-- https://mvnrepository.com/artifact/com.itextpdf/itextpdf -->
<dependency>
<groupId>com.itextpdf</groupId>
<artifactId>itextpdf</artifactId>
<version>5.5.13</version>
</dependency>
</dependencies>
然后上代码:
接口层:
import cn.hutool.core.io.file.FileWriter;
import cn.hutool.core.util.RandomUtil;
import com.xr.common.constant.Constants;
import com.xr.common.core.domain.R;
import com.xr.rent.underlease.underleaseroom.domain.RentUnderLeaseRoom;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.apache.velocity.Template;
import org.apache.velocity.VelocityContext;
import org.apache.velocity.app.Velocity;
import org.apache.velocity.app.VelocityEngine;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.util.Properties;
@Api(tags = "获取租赁模板")
@RestController
@RequestMapping("/redPdfModelController")
public class RedPdfModelController {
@ApiOperation(value = "获取传入数据后的内容", httpMethod = "GET")
@PostMapping("/getModel")
//这里传值
public R get(@RequestBody RentUnderLeaseRoom rentUnderLeaseRoom, HttpServletResponse response) throws FileNotFoundException {
VelocityEngine ve = new VelocityEngine();
Properties p = new Properties();
// 加载classpath目录下的vm文件,指定vm文件加载目录
p.setProperty("resource.loader.file.class", "org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader");
p.setProperty(Velocity.INPUT_ENCODING, Constants.UTF8);
// 初始化Velocity引擎,指定配置Properties
// Velocity.init(p);
ve.setProperty(Velocity.ENCODING_DEFAULT, "UTF-8");
ve.setProperty(Velocity.INPUT_ENCODING, "UTF-8"); //指定编码格式,避免生成模板就造成乱码
ve.init(p);
//取得velocity的模板
Template t = ve.getTemplate("vmmodel/contract.html.vm", "UTF-8");
//取得velocity的上下文
VelocityContext context = new VelocityContext();
//往vm中写入信息
//写入自己要插入的信息,
context.put("username", rentUnderLeaseRoom.getUnitName());
StringWriter writer = new StringWriter();
//把数据填入上下文
t.merge(context, writer);
//输出流
String testPath = "";
String pdfDownlad = "";
String out = writer.toString();
String osName = System.getProperty("os.name");
if (osName.toLowerCase().startsWith("win")) {
testPath = "D:\\checkHtml\\" + RandomUtil.randomNumbers(20) + ".html";
pdfDownlad = "D:\\testPdf\\" + RandomUtil.randomNumbers(20) + ".pdf";
} else {
testPath = "/opt/checkHtml/" + RandomUtil.randomNumbers(20) + ".html";
pdfDownlad = "/opt/checkPdf/" + RandomUtil.randomNumbers(20) + ".pdf";
}
File file = new File(testPath);
FileWriter fileWriter = FileWriter.create(file);
fileWriter.write(out);
try {
FileTypeConvertUtil.html2pdf(file.getAbsolutePath(), pdfDownlad);
} catch (Exception e) {
throw new RuntimeException(e);
}
BufferedInputStream bis = null;
OutputStream os = null;
FileInputStream fileInputStream = null;
try {
fileInputStream = new FileInputStream(pdfDownlad);
byte[] buff = new byte[1024];
bis = new BufferedInputStream(fileInputStream);
os = response.getOutputStream();
int i = bis.read(buff);
while (i != -1) {
os.write(buff, 0, buff.length);
i = bis.read(buff);
os.flush();
}
os.flush();
os.close();
} catch (IOException e) {
e.printStackTrace();
} finally {
if (bis != null) {
try {
bis.close();
fileInputStream.close();
} catch (IOException e) {
e.printStackTrace();
return R.fail("导出失败");
}
}
}
response.setCharacterEncoding("utf-8");
response.setContentType("application/pdf");
response.setHeader("Content-Disposition", "attachment; filename=Encrypt.pdf");
return R.ok("下载成功");
}
}
用到的工具类: 通过这个工具类来讲html转换为pdf,可先用main方法进行测试。
package com.xr.rent.readpdfmodel.controller;
import com.itextpdf.text.pdf.BaseFont;
import org.xhtmlrenderer.pdf.ITextFontResolver;
import org.xhtmlrenderer.pdf.ITextRenderer;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.OutputStream;
/**
* 文件格式转换工具类
*
* @author lbj
* <p>
* 2015-10-8 上午10:52:22
*/
public class FileTypeConvertUtil {
/**
* 将HTML转成PD格式的文件。html文件的格式比较严格
*
* @param htmlFile
* @param pdfFile
* @throws Exception
*/
// <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd ">
public static void html2pdf(String htmlFile, String pdfFile) throws Exception {
// step 1
String url = new File(htmlFile).toURI().toURL().toString();
System.out.println(url);
// step 2
OutputStream os = new FileOutputStream(pdfFile);
ITextRenderer renderer = new ITextRenderer();
renderer.setDocument(url);
// step 3 解决中文支持
ITextFontResolver fontResolver = renderer.getFontResolver();
if ("linux".equals(getCurrentOperatingSystem())) {
fontResolver.addFont("/usr/share/fonts/chiness/simsun.ttc", BaseFont.IDENTITY_H, BaseFont.EMBEDDED);
} else {
fontResolver.addFont("c:/Windows/Fonts/simsun.ttc", BaseFont.IDENTITY_H, BaseFont.NOT_EMBEDDED);
}
renderer.layout();
renderer.createPDF(os);
os.close();
System.out.println("create pdf done!!");
}
public static String getCurrentOperatingSystem() {
String os = System.getProperty("os.name").toLowerCase();
System.out.println("---------当前操作系统是-----------" + os);
return os;
}
public static void main(String[] args) {
// String htmlFile = "/home/lbj/sign.jsp";
// String pdfFile = "/home/lbj/sign.pdf";
String htmlFile = "d:/table.html";
String pdfFile = "d:/testoone2.pdf";
try {
FileTypeConvertUtil.html2pdf(htmlFile, pdfFile);
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
}
}
vm模板: 使用此模板来进行渲染
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html lang="en" xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta charset="UTF-8"/>
<title>表格样式</title>
<meta name="viewport" content="initial-scale=1, maximum-scale=1, user-scalable=no, width=device-width"/>
<link rel="stylesheet" href="https://static.loyalvalleycapital.com/web/css/frame.css"/>
<style>
</style>
</head>
<body class="bg-white pb-3" style="font-family: SimSun;">
<h1>合同</h1>
<h2>甲方:${username}</h2>
</body>
</html>
以上就是全部代码,下面是效果图。
可以自定义css和html表现来实现效果。