java项目使用wkhtmltopdf实现模板导出pdf

wkhtmltopdf介绍

wkhtmltopdf是一款安装在服务端的pdf导出插件,只需要通过命令行就能调用,将html文件转换成pdf文件;
使用这款插件,java程序中不需要额外引入任何依赖。

使用前准备

去官网【https://wkhtmltopdf.org/】下载安装插件

使用方法

一、控制台简单使用

  1. 准备好一个用来导出的html文件

  2. 打开插件安装的目录,并在此处打开控制台窗口

  3. 在控制台输入命令 .\wkhtmltopdf.exe {html文件的地址} {要导出的地址}
    导出成功!

二、整合java程序使用
在我的项目中使用了freemarker将ftl网页模板文件与数据绑定,生成html文件,然后再调用wkhtmltopdf生成pdf文件
话不多说,直接上代码

/**
 * HTML转PDF工具类(WK实现,样式更完善)
 *
 * @author wangmeng
 * @since 2021/7/15
 */
@Slf4j
public class Html2PdfUtils {

    /**
     * 根据模板导出pdf文件(A4尺寸)
     *
     * @param templateName 模板名称
     * @param data         用来渲染的页面数据
     * @param savePath     导出路径
     * @param fileName     pdf名称
     */
    public static void makePdf(String templateName, Object data, String savePath, String fileName) {
        makePdf(templateName, data, savePath, fileName, PageSize.defaultSize);
    }


    /**
     * 根据模板导出pdf文件
     *
     * @param templateName 模板名称
     * @param data         用来渲染的页面数据
     * @param savePath     导出路径
     * @param fileName     pdf名称
     * @param pageSize     页面尺寸
     */
    public static void makePdf(String templateName, Object data, String savePath, String fileName, PageSize pageSize) {
        FileUtils.createFileFolder(savePath);
        String htmlData = getContent(templateName, data);
        try {
            createPdf(htmlData, savePath, fileName, pageSize);
        } catch (Exception e) {
            log.error(e.getMessage());
            throw new CustomException("导出pdf文件失败!");
        }
    }

    /**
     * 获取pdf模板
     *
     * @param templateName 模板名称
     * @param data         用来渲染的页面数据
     * @return 渲染后的页面
     */
    private static String getContent(String templateName, Object data) {
        if (StringUtils.isBlank(templateName)) {
            throw new CustomException("模板路径和模板名称不能为空!");
        }
        //使用数据渲染模板
        try (StringWriter writer = new StringWriter()) {
            //FreeMarker配置
            Configuration config = new Configuration(Configuration.VERSION_2_3_25);
            config.setDefaultEncoding("UTF-8");
            config.setDirectoryForTemplateLoading(new File(ConfigUtils.getPdfTemplatePath())); //设置读取模板的目录
            config.setTemplateExceptionHandler(TemplateExceptionHandler.RETHROW_HANDLER);
            config.setLogTemplateExceptions(false);
            Template template = config.getTemplate(templateName);//根据模板名称 获取对应模板
            template.process(data, writer);
            writer.flush();
            return writer.toString();
        } catch (IOException | TemplateException ioException) {
            log.error(ioException.getMessage());
            throw new CustomException(GlobalI18nConstant.TEMPLATE_ERROR);
        }
    }

    /**
     * 根据html文件生成pdf
     *
     * @param htmlContent html
     * @param savePath    导出路径
     * @param fileName    文件名
     * @param pageSize    尺寸
     * @throws IOException
     */
    private static void createPdf(String htmlContent, String savePath, String fileName, PageSize pageSize) throws IOException {
        //创建临时文件夹,存放渲染完的html文件
        String time = DateUtils.toString(new Date(), DateUtils.YYYY_MM_DD_HH_MM_SS3);
        String tempPath = ConfigUtils.getBaseDir() + ConfigUtils.getBaseTempDir() + File.separator + time + IdUtils.uuid();
        FileUtils.createFileFolder(tempPath);
        FileOutputStream fileoutputstream = null;
        String space = GlobalConstant.SPACE;
        //临时文件名,防止文件名中带空格
        String tempFileName = IdUtils.uuid() + ".pdf";
        try {
            File tempHtml = new File(tempPath + File.separator + "temp.html");
            fileoutputstream = new FileOutputStream(tempHtml);
            fileoutputstream.write(htmlContent.getBytes(StandardCharsets.UTF_8));
            StringBuilder cmd = new StringBuilder();
            cmd.append(ConfigUtils.getWkhtmltopdf()).append(space);
            //优先枚举尺寸类型
            if (pageSize.getSize() != null) {
                cmd.append("--page-size").append(space).append(pageSize.getSize());
            } else {
                cmd.append("--page-width").append(space).append(pageSize.getWidth()).append(space)
                        .append("--page-height").append(space).append(pageSize.getHeight());
            }
            // 若PDF有图片标签 下载SRC路径地址下的图片
            cmd.append(space).append("--image-quality 94");
            cmd.append(space).append(tempPath).append(File.separator).append("temp.html").append(space).append(savePath).append(File.separator).append(tempFileName);
            Runtime runtime = Runtime.getRuntime();
            Process proc = runtime.exec(cmd.toString());
            proc.waitFor();

            //修改文件名
            File pdf = new File(savePath + File.separator + tempFileName);
            File newFile = new File(pdf.getParent() + File.separator + fileName);
            int i = 1;
            int index = fileName.lastIndexOf(".");
            String prefix = fileName.substring(0, index);
            String suffix = fileName.substring(index);
            while (newFile.exists()) {
                newFile = new File(pdf.getParent() + File.separator + prefix + '(' + i + ')' + suffix);
                i++;
            }
            if (!pdf.renameTo(newFile)) {
                throw new CustomException("文件重命名失败!");
            }
        } catch (Exception e) {
            log.error(e.getMessage());
        } finally {
            if (fileoutputstream != null) {
                fileoutputstream.close();
            }
            //删除临时文件夹
            FileUtils.deleteDirectory(tempPath);
        }
    }
}

我的方法整合了设置页面尺寸,导出图片功能,除此之外wkhtmltopdf还有更多骚操作等待大家发现,想要了解就立即打开官网吧

posted @ 2021-09-14 10:12  小白白白白白白白白白  阅读(1836)  评论(0编辑  收藏  举报