发布于2023-01-18 23:00 阅读(801) 评论(0) 点赞(4) 收藏(4)
请一定要使用下面的这种方式获取系统的可执行命令,否则会报一堆的找不到目录等错误!!!
- 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之间的耗时对比;
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
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里面删除由于工具转换过程中生成的临时文件
- 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();
- }
- }
- }
- }
- }
- }

作者:Jjxj
链接:http://www.qianduanheidong.com/blog/article/494767/b9bbc172b7b6306f6d93/
来源:前端黑洞网
任何形式的转载都请注明出处,如有侵权 一经发现 必将追究其法律责任
昵称:
评论内容:(最多支持255个字符)
---无人问津也好,技不如人也罢,你都要试着安静下来,去做自己该做的事,而不是让内心的烦躁、焦虑,坏掉你本来就不多的热情和定力
Copyright © 2018-2021 前端黑洞网 All Rights Reserved 版权所有,并保留所有权利。 京ICP备18063182号-3
投诉与举报,广告合作请联系vgs_info@163.com或QQ3083709327
免责声明:网站文章均由用户上传,仅供读者学习交流使用,禁止用做商业用途。若文章涉及色情,反动,侵权等违法信息,请向我们举报,一经核实我们会立即删除!