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還有更多騷操作等待大家發現,想要了解就立即打開官網吧


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM