WKHtmltoPdf

这篇具有很好参考价值的文章主要介绍了WKHtmltoPdf。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

踩过的坑

请一定要使用下面的这种方式获取系统的可执行命令,否则会报一堆的找不到目录等错误!!!

 String osname = System.getProperty("os.name").toLowerCase();
 String cmd = osname.contains("windows") ? "where wkhtmltopdf" : "which wkhtmltopdf";
 p = Runtime.getRuntime().exec(cmd);

由于wkhtmltoPdf是基于操作系统层面的pdf转换,因此,程序想获得Html转换pdf就需要经历四次IO操作,如果pdf的大小大于3M时,就会变得缓慢,建议考虑使用itext5进行pdf转换。下面是itext4、itext5和wkhtmltoPdf之间的耗时对比;

wkhtmltopdf,pdf工具,java,前端,html 

原理

1、wkhtmltopdf是一个独立安装、通过命令行交互、开源免费的将html内容转为pdf或图片的工具,命令行交互意味着只要能够调用本地命令(cmd或shell等)的开发语言均可使用,比如Java。其本质是使用内置浏览器内核渲染目标网页,然后再将网页渲染结果转换为PDF文档或图片。wkhtmltopdf官网地址:wkhtmltopdf,选择合适的系统版本安装即可。

2、创建待转换的目标HTML页面,可用任何熟悉的技术栈,要注意的一点是尽量保存页面为静态,尽量减少动态效果、交互。wkhtmltopdf也可支持直接转换html文件,不过还是建议以url方式来转换,更简便。

3、 部署运行html web服务,切换到bin目录,运行命令行进行转换:

/wkhtmltopdf http://yourdomain/target.html SAVE_PATH/target.pdf

4、命令结构:wkhtmltopdf [GLOBAL OPTION]... [OBJECT]... <output file>

在命令行上可通过 wkhtmltopdf –H 来查看所有的配置说明。官网文档:https://wkhtmltopdf.org/usage/wkhtmltopdf.txt

JAVA调用

1、首先需要封装命令参数

private static String buildCmdParam(String srcAbsolutePath, String destAbsolutePath, Integer pageHeight, Integer pageWidth) {
        StringBuilder cmd = new StringBuilder();
        cmd.append(findExecutable()).append(space)
                .append("--margin-left").append(space)
                .append("0").append(space)
                .append("--margin-right").append(space)
                .append("0").append(space)
                .append("--margin-top").append(space)
                .append("0").append(space)
                .append("--margin-bottom").append(space)
                .append("0").append(space)
                .append("--page-height").append(space)
                .append(pageHeight).append(space)
                .append("--page-width").append(space)
                .append(pageWidth).append(space)

                .append(srcAbsolutePath).append(space)
//                .append("--footer-center").append(space)
//                .append("[page]").append(space)
//                .append("--footer-font-size").append(space)
//                .append("14").append(space)
//
//                .append("--disable-smart-shrinking").append(space)
//                .append("--load-media-error-handling").append(space)
//                .append("ignore").append(space)
//                .append("--load-error-handling").append(space)
//                .append("ignore").append(space)
//                .append("--footer-right").append(space)
//                .append("WanG提供技术支持").append(space)
                .append(destAbsolutePath);
        return cmd.toString();
    }
    /**
     * 获取当前系统的可执行命令
     *
     * @return
     */
    public static String findExecutable() {
        Process p;
        try {
            String osname = System.getProperty("os.name").toLowerCase();
            String cmd = osname.contains("windows") ? "where wkhtmltopdf" : "which wkhtmltopdf";
            p = Runtime.getRuntime().exec(cmd);
            new Thread(new ProcessStreamHandler(p.getErrorStream())).start();
            p.waitFor();
            return IOUtils.toString(p.getInputStream(), Charset.defaultCharset());
        } catch (IOException e) {
            log.info("根据当前系统返回 wkhtmltopdf 执行命令失败,IO异常:", e);
        } catch (InterruptedException e) {
            log.info("根据当前系统返回 wkhtmltopdf 执行命令失败,中断异常:", e);
        }
        return "";
    }

2、获取当前系统的命令参数

Process proc = Runtime.getRuntime().exec(finalCmd);

3、等待程序执行结果,并以ByteArrayOutputStream形式返回,最后在finally里面删除由于工具转换过程中生成的临时文件文章来源地址https://www.toymoban.com/news/detail-822169.html

private static ByteArrayOutputStream doProcess(String finalCmd, File htmlTempFile, File wkpdfDestTempFile) {
        InputStream is = null;
        try {
            Process proc = Runtime.getRuntime().exec(finalCmd);
            new Thread(new ProcessStreamHandler(proc.getInputStream())).start();
            new Thread(new ProcessStreamHandler(proc.getErrorStream())).start();

            proc.waitFor();
            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            is = new FileInputStream(wkpdfDestTempFile);
            byte[] buf = new byte[1024];

            while (is.read(buf, 0, buf.length) != -1) {
                baos.write(buf, 0, buf.length);
            }

            return baos;
        } catch (IOException | InterruptedException e) {
            log.error("html转换pdf出错", e);
            throw new RuntimeException("html转换pdf出错了");
        } finally {
            if (htmlTempFile != null) {
                boolean delete = htmlTempFile.delete();
            }
            if (wkpdfDestTempFile != null) {
                boolean delete = wkpdfDestTempFile.delete();
            }
            if (is != null) {
                try {
                    is.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

完整代码如下

import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.CharsetUtil;
import cn.hutool.core.util.StrUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.IOUtils;

import java.io.*;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.util.Random;

@Slf4j
public class WkHtmltoxPdf {
    //空格
    private static final String space = " ";

    //文件前缀
    private static final String PREFIX = "tempFile";

    //文件后缀-html
    private static final String SUFIX_HTML = ".html";
    //文件后缀pdf
    private static final String SUFIX_PDF = ".pdf";

    private static final Random RANDOM = new Random(100);

    private static String FILEDIR_PATH = "/Users/yangfan/tools/wkhtmltox";

    private static final Integer PAGE_HEIGHT = 60;

    private static final Integer PAGE_WIDTH = 100;

    public static void main(String[] args) {
        testWkPdf(getHtml(), PAGE_HEIGHT, PAGE_WIDTH);
    }

    public static void testWkPdf(String html, Integer pageHeight, Integer pageWidth) {
        byte[] bytes = html2pdf(html, pageHeight, pageWidth).toByteArray();
        storagePdf(bytes, FILEDIR_PATH, RANDOM.nextInt() + SUFIX_PDF);
    }

    /**
     * 存储pdf文件
     *
     * @param bfile    pdf字节流
     * @param filePath 文件路径
     * @param fileName 文件名称
     */
    public static void storagePdf(byte[] bfile, String filePath, String fileName) {
        BufferedOutputStream bos = null;
        FileOutputStream fos = null;
        File file = null;
        try {
            File dir = new File(filePath);
            if ((!dir.exists()) && (dir.isDirectory())) {
                boolean mkdirs = dir.mkdirs();
            }
            file = new File(filePath + "/" + fileName);
            fos = new FileOutputStream(file);
            bos = new BufferedOutputStream(fos);
            bos.write(bfile);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (bos != null) {
                try {
                    bos.close();
                } catch (IOException e1) {
                    e1.printStackTrace();
                }
            }
            if (fos != null) {
                try {
                    fos.close();
                } catch (IOException e1) {
                    e1.printStackTrace();
                }
            }
        }
    }

    /**
     * 将传入的页面转换成pdf,返回pdf字节数组
     * 默认自动随机生成文件名称
     *
     * @param html html页面信息
     * @return byte[] pdf字节流
     */
    public static ByteArrayOutputStream html2pdf(String html, Integer pageHeight, Integer pageWidth) {
        String fileName = System.currentTimeMillis() + RANDOM.nextInt() + "";
        String dest = FILEDIR_PATH;
        return doHtml2pdf(html, dest, pageHeight, pageWidth);
    }

    private static ByteArrayOutputStream doHtml2pdf(String html, String dest, Integer pageHeight, Integer pageWidth) {
        String wkhtmltopdf = findExecutable();
        //将内存中的html文件存储到一个临时地方
        File htmlTempFile = createFile(PREFIX, SUFIX_HTML, dest);
        FileUtil.writeString(html, htmlTempFile, CharsetUtil.UTF_8);

        //wk转换pdf之后的pdf存储文件地址
        File wkpdfDestTempFile = createFile(PREFIX, SUFIX_PDF, dest);

        if (StrUtil.isBlank(wkhtmltopdf)) {
            log.info("no wkhtmltopdf found!");
            throw new RuntimeException("html转换pdf出错了,未找到wkHtml工具");
        }

        String srcAbsolutePath = htmlTempFile.getAbsolutePath();
        String destAbsolutePath = wkpdfDestTempFile.getAbsolutePath();

        File parent = wkpdfDestTempFile.getParentFile();
        if (!parent.exists()) {
            boolean dirsCreation = parent.mkdirs();
            log.info("create dir for new file,{}", dirsCreation);
        }

        String finalCmd = buildCmdParam(srcAbsolutePath, destAbsolutePath, pageHeight, pageWidth);

        return doProcess(finalCmd, htmlTempFile, wkpdfDestTempFile);

    }

    /**
     * 执行wkHtmltox命令,读取生成的的pdf文件,输出执行结果,最后删除由于执行wk命令生成的零时的pdf文件和html文件
     *
     * @param finalCmd          cmd命令
     * @param htmlTempFile      html零时文件
     * @param wkpdfDestTempFile 生成的pdf文件
     * @return byte[] pdf字节流
     */
    private static ByteArrayOutputStream doProcess(String finalCmd, File htmlTempFile, File wkpdfDestTempFile) {
        InputStream is = null;
        try {
            Process proc = Runtime.getRuntime().exec(finalCmd);
            new Thread(new ProcessStreamHandler(proc.getInputStream())).start();
            new Thread(new ProcessStreamHandler(proc.getErrorStream())).start();

            proc.waitFor();
            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            is = new FileInputStream(wkpdfDestTempFile);
            byte[] buf = new byte[1024];

            while (is.read(buf, 0, buf.length) != -1) {
                baos.write(buf, 0, buf.length);
            }

            return baos;
        } catch (IOException | InterruptedException e) {
            log.error("html转换pdf出错", e);
            throw new RuntimeException("html转换pdf出错了");
        } finally {
            if (htmlTempFile != null) {
                boolean delete = htmlTempFile.delete();
            }
            if (wkpdfDestTempFile != null) {
                boolean delete = wkpdfDestTempFile.delete();
            }
            if (is != null) {
                try {
                    is.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    public static File createFile(String prefix, String sufix, String fileDirPath) {
        File file = null;
        File fileDir = new File(fileDirPath);
        try {
            file = File.createTempFile(prefix, sufix, fileDir);
        } catch (IOException e) {
            log.info("创建文件失败:", e.getCause());
        }
        return file;
    }

    private static String buildCmdParam(String srcAbsolutePath, String destAbsolutePath, Integer pageHeight, Integer pageWidth) {
        StringBuilder cmd = new StringBuilder();
        cmd.append(findExecutable()).append(space)
                .append("--margin-left").append(space)
                .append("0").append(space)
                .append("--margin-right").append(space)
                .append("0").append(space)
                .append("--margin-top").append(space)
                .append("0").append(space)
                .append("--margin-bottom").append(space)
                .append("0").append(space)
                .append("--page-height").append(space)
                .append(pageHeight).append(space)
                .append("--page-width").append(space)
                .append(pageWidth).append(space)

                .append(srcAbsolutePath).append(space)
//                .append("--footer-center").append(space)
//                .append("[page]").append(space)
//                .append("--footer-font-size").append(space)
//                .append("14").append(space)
//
//                .append("--disable-smart-shrinking").append(space)
//                .append("--load-media-error-handling").append(space)
//                .append("ignore").append(space)
//                .append("--load-error-handling").append(space)
//                .append("ignore").append(space)
//                .append("--footer-right").append(space)
//                .append("WanG提供技术支持").append(space)
                .append(destAbsolutePath);
        return cmd.toString();
    }

    /**
     * 获取当前系统的可执行命令
     *
     * @return
     */
    public static String findExecutable() {
        Process p;
        try {
            String osname = System.getProperty("os.name").toLowerCase();
            String cmd = osname.contains("windows") ? "where wkhtmltopdf" : "which wkhtmltopdf";
            p = Runtime.getRuntime().exec(cmd);
            new Thread(new ProcessStreamHandler(p.getErrorStream())).start();
            p.waitFor();
            return IOUtils.toString(p.getInputStream(), Charset.defaultCharset());
        } catch (IOException e) {
            log.info("根据当前系统返回 wkhtmltopdf 执行命令失败,IO异常:", e);
        } catch (InterruptedException e) {
            log.info("根据当前系统返回 wkhtmltopdf 执行命令失败,中断异常:", e);
        }
        return "";
    }

    private static class ProcessStreamHandler implements Runnable {
        private InputStream is;

        public ProcessStreamHandler(InputStream is) {
            this.is = is;
        }

        @Override
        public void run() {
            BufferedReader reader = null;
            try {
                InputStreamReader isr = new InputStreamReader(is, StandardCharsets.UTF_8);
                reader = new BufferedReader(isr);
                String line;
                while ((line = reader.readLine()) != null) {
                    log.debug("---++++++++++--->" + line);
                }
            } catch (IOException e) {
                e.printStackTrace();
            } finally {
                if (reader != null) {
                    try {
                        reader.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }
        }
    }
}

到了这里,关于WKHtmltoPdf的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • VUE通用后台管理系统(四)前端导出文件(CSV、XML、HTML、PDF、EXCEL)

    常见的导出格式:CSV、XML、HTML、PDF、EXCEL 1)准备工作 安装所需相关依赖 前两个是PDF格式需要的依赖,后两个是excel格式所需,如果没有需求这两种格式的可以忽略这一步 然后画页面   页面效果 2)导出CSV格式的文件 新建src/utils/utils.js文件 写入exportCsv方法,columns为表头,

    2024年02月05日
    浏览(59)
  • java实现html转pdf

    1.需求:将一个html页面转成pdf格式。 2.方法:在实现之前先考虑一个问题,pdf是前端生成还是后端生成。这里采用pdfbox+itext(PDF文件名可自定义)技术在服务端生成。 优点:免费,不需要安转软件,速度快,对于开发者而言,开发中仅需导入相应jar,且易部署。 缺点:对于

    2024年02月11日
    浏览(31)
  • Java HTML生成PDF(格式不变)

    Java是大规模和企业级应用程序最常用的编程语言之一。PDF 格式代表可移植文档格式,为人们提供了一种简单、可靠的方式来呈现和交换文档 - 无论查看文档的任何人使用何种软件、硬件或操作系统。因此,pdf 是一种广泛使用的格式,用于在软件应用程序中生成文档。 HTML 用

    2024年02月12日
    浏览(43)
  • 前端生成pdf之html2canvas+jsPDF,以及解决图片不显示bug

    开发背景: 需要给页面中相应的内容生成pdf,查找文档后发现要用到两个插件。html2canvas 以及 jsPDF html2canvas 给dom结构转化为canvas,然后生成各种类型图片 jsPDF 把canvas 生成的图片url 转化为pdf 参数 image:表示要插入的图片资源,可以是图片文件的路径或者base64编码字符串。

    2024年02月02日
    浏览(54)
  • 3D数据导出工具HOOPS Publish:3D数据查看、生成标准PDF或HTML文档!

    HOOPS中文网 http://techsoft3d.evget.com/ 一、3D导出SDK HOOPS Publish是一款功能强大的SDK,可以创作丰富的工程数据并将模型文件导出为各种行业标准格式,包括PDF、STEP、JT和3MF。HOOPS Publish核心的3D数据模型是经过ISO认证的PRC格式(ISO 14739-1:2014),它为装配树、拓扑和几何、产品制造信息

    2024年02月10日
    浏览(43)
  • 【aspose之三】【springboot】java使用aspose.html 的cloud版html转pdf,html2pdf

    把url网页或本地文件html转换pdf 1.maven配置 2.代码 本地文件 html转pdf 可本地文件或url转换 pdf布局设置 2.密钥及配置 aspose配置

    2024年02月06日
    浏览(40)
  • java html转word、pdf(包含图片)

    maven依赖 核心代码 maven依赖 核心代码 Base64ImgReplacedElementFactory类

    2024年02月07日
    浏览(57)
  • 如何通过Java代码将 PDF文档转为 HTML格式

    虽然PDF文件适合用于打印和发布,但不适合所有类型的文档。例如,包含复杂图表和图形的文档可能无法在PDF中呈现得很好。但是HTML文件可以在任何可运行浏览器的计算机上进行阅读并显示。并且HTML还具有占用服务器资源较小,便于搜索引擎收录的特点。那么今天这篇文章就

    2024年02月05日
    浏览(58)
  • java中使用Jsoup和Itext实现将html转换为PDF

    1.在build.gradle中安装所需依赖: 2.创建工具类,实现转换方法 3.base64过滤类: 4.字体类代码,window用户可在C:windowsfont中寻找自己所需字体即可。我这里用的为黑体: simhei.ttf 效果如下: html页面预览: pdf页面预览:    

    2024年02月14日
    浏览(37)
  • Java后端返回PDF预览给前端

    前端要预览服务器PDF 可直接将要blob流返回给前端 即可用浏览器自带pdf预览功能打开,现有两种方式 方式1 返回blob流给前端 代码如下        此时 前端解析可直接拿返回的文件流 例子如下 但有的时候 不想返回文件流 可把文件返回为base64 (注意 base64可能超长)此时代码修

    2024年02月08日
    浏览(58)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包