先说一下,Itext其实已经满足了需求,但是页面不好看,由于这点,所以换成wkhtmltopdf
但是,我们知道wk,是软件的方式,部署的步骤:下载->安装->运行命令
官网下载:wkhtmltopdf
在centos下使用: cat /etc/redhat-release 即可查看自己的centos是啥版本了。
下载之后,上传到linux:
rpm -vih wkhtmltox-0.12.6-1.centos7.x86_64.rpm
就安装完成了。
最好提供map类型的数据。因为模板WebContent接收的是map类型
Map<String, Object> data = BeanUtil.beanToMap(productPdfVo);
pdfUtil.downloadPdf(templateEngine, request, "index62", data, response, "ws.pdf", productPdfVo.getFlag());
以下代码含义,获取项目的路径地址,然后创建static目录,创建出html文件,再把thymeleaf生成的模板转为inputStream输入流,再使用hutool的IoUtil工具类,把输入流的内容转到输出流中,
再用wk封装的工具类,把html转为pdf即可。
public void downloadPdf(TemplateEngine templateEngine, HttpServletRequest request, String templateName, Map<String, Object> listVars, HttpServletResponse response, String fileName,String flag) {
// String path = this.getClass().getResource("/").getPath();
String path = System.getProperty("user.dir");
try (ServletOutputStream out = response.getOutputStream()) {
File file = new File(path + "/static/ws.html");
File parentFile = file.getParentFile();
if (!parentFile.exists()) {
parentFile.mkdirs();
}
FileOutputStream fileOutputStream = new FileOutputStream(new File(path+"/static/ws.html"));
WebContext ctx = new WebContext(request, response,request.getServletContext(),request.getLocale(), listVars);
String htmlContent = templateEngine.process(templateName, ctx);
InputStream in = new ByteArrayInputStream(htmlContent.getBytes("utf-8"));
IoUtil.copy(in, fileOutputStream);
boolean convert = Html2PdfUtil.convert(path + "/static/ws.html", path + "/static/demo.pdf");
if(convert){
FileInputStream fi = new FileInputStream(new File(path+"/static/demo.pdf"));
IoUtil.copy(fi, out);
IoUtil.close(fi);
}else{
throw new BizException("转换pdf异常");
}
IoUtil.close(in);
IoUtil.close(fileOutputStream);
} catch (Exception e) {
log.error(e.getMessage(), e);
}finally {
File file=new File(path+"/static/ws.html");
if (file.exists()){
file.delete();
}
File file1=new File(path+"/static/demo.pdf");
if (file1.exists()){
file1.delete();
}
}
}
@Slf4j
public class Html2PdfUtil {
/**
* wkhtmltopdf命令地址
*/
private static final String TOPDFTOOL = "/usr/local/bin/wkhtmltopdf";
/**
* html转pdf
*
* @param srcPath
* html路径,可以是硬盘上的路径,也可以是网络路径
* @param destPath
* pdf保存路径
* @return 转换成功返回true
*/
public static boolean convert(String srcPath, String destPath) {
File file = new File(destPath);
File parent = file.getParentFile();
// 如果pdf保存路径不存在,则创建路径
if (!parent.exists()) {
parent.mkdirs();
}
StringBuilder cmd = new StringBuilder();
cmd.append(TOPDFTOOL);
cmd.append(" --enable-local-file-access ");
cmd.append(" --disable-smart-shrinking ");
cmd.append(" --page-size ");
cmd.append(" A3 ");
cmd.append(" ");
cmd.append(srcPath);
cmd.append(" ");
// cmd.append(" --page-size A4 ");// 设置纸张大小
cmd.append(destPath);
boolean result = true;
try {
System.out.println(cmd);
Process proc = Runtime.getRuntime().exec(cmd.toString());
HtmlToPdfInterceptor error = new HtmlToPdfInterceptor(proc.getErrorStream());
HtmlToPdfInterceptor output = new HtmlToPdfInterceptor(proc.getInputStream());
error.start();
output.start();
proc.waitFor();
System.out.println("HTML2PDF成功");
} catch (Exception e) {
System.out.println(("HTML2PDF失败"));
e.printStackTrace();
log.error("转换pdf异常: {}",e);
result = false;
}
return result;
}
public static class HtmlToPdfInterceptor extends Thread {
private InputStream is;
public HtmlToPdfInterceptor(InputStream is) {
this.is = is;
}
public void run() {
try {
InputStreamReader isr = new InputStreamReader(is, "utf-8");
BufferedReader br = new BufferedReader(isr);
br.readLine();
} catch (Exception e) {
e.printStackTrace();
}
}
}
public static void main(String[] args) {
String htmlPath = "http://www.baidu.com/";
String pdfPath = "/Users/wangshuai/test2222.pdf";
Html2PdfUtil.convert(htmlPath, pdfPath);
}
}
其中用到了wk的这个参数--enable-local-file-access,主要是转pdf的时候,有图片,首先看看模板转为html中,图片是否加载成功。如果加载成功,再看pdf,pdf不成功的原因,大概就是图片的相对路径不对,所以加上这个参数,可以使用本地文件,写相对路径即可。
模板是这么写的。