thymeleaf模板生成html,再转pdf,弃用IText,转用wkhtmltopdf

先说一下,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不成功的原因,大概就是图片的相对路径不对,所以加上这个参数,可以使用本地文件,写相对路径即可。

模板是这么写的。

 

 

 

猜你喜欢

转载自blog.csdn.net/weixin_38340874/article/details/124473917