Java html模板生成PDF

一、Maven依賴css

       <dependency>
            <groupId>org.freemarker</groupId>
            <artifactId>freemarker</artifactId>
            <version>2.3.23</version>
        </dependency>

        <dependency>
            <groupId>com.itextpdf</groupId>
            <artifactId>itextpdf</artifactId>
            <version>5.4.2</version>
        </dependency>
        <dependency>
            <groupId>com.itextpdf.tool</groupId>
            <artifactId>xmlworker</artifactId>
            <version>5.4.1</version>
        </dependency>
        <dependency>
            <groupId>com.itextpdf</groupId>
            <artifactId>itext-asian</artifactId>
            <version>5.2.0</version>
        </dependency>
        <dependency>
            <groupId>org.xhtmlrenderer</groupId>
            <artifactId>flying-saucer-pdf</artifactId>
            <version>9.0.3</version>
        </dependency>

 

二、pdfTemplate.ftl模板html

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
    <title></title>
    <meta http-equiv="content-type" content="text/html;charset=utf-8"></meta>
    <style type="text/css">
        body {
            font-family: SimSun;
        }
        @page{size:A3 }
        .pianyi{
            display:block;
            font-family:SimSun;
            padding-left:15px;
            padding-right:15px;
            -webkit-margin-after:16px;
            -webkit-margin-before:16px;
            -webkit-margin-end:0px;
            -webkit-margin-start:0px;
        }
        .textSpan {
            padding-left: 15px;
            padding-right: 15px;
            line-height: 27px;
        }

    </style>
</head>
<body>
<h3 style="text-align: center;">電子受權書</h3>
<p class="pianyi">被受權人名稱</p>
<span class="textSpan">受權人(申請人)姓名: ${name}</span><br></br>
<span class="textSpan">身份證號: ${idCardNo}</span><br></br>
<span class="textSpan">受權協議生效日期: ${dateD} </span><br></br>
<br/>
<div style="word-wrap: break-word;word-break: break-all;overflow: hidden; ">
    ${content}
</div>
<div style="padding-left:15px;padding-right:15px;">簽名處:</div>
</body>
</html>

 

三、建立GeneratePdf類java

package com.wap.common;

import com.itextpdf.text.pdf.BaseFont;
import freemarker.template.Configuration;
import freemarker.template.Template;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.xhtmlrenderer.pdf.ITextRenderer;

import java.io.File;
import java.io.FileOutputStream;
import java.io.OutputStream;
import java.io.StringWriter;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;

/**
 * 生成Pdf
 * Created by dgl on 2018/8/6.
 */
public class GeneratePdf implements Runnable {

    private static Logger logger = LoggerFactory.getLogger(GeneratePdf.class);

    private String webPath; //= PathUtil.getPath();//web根目錄
    /**
     * 指定FreeMarker模板文件的位置
     */
    private String templatePath;

    /**
     * freeMarker模板文件名稱
     */
    private static String templateFileName = "pdfTemplate.ftl";

    /**
     * 圖片路徑 —— 默認是classpath下面的images文件夾
     */
    private static String imagePath = "/upload/";

    /**
     * 指定編碼
     */
    private static String encoding = "UTF-8";

    /**
     * 字體   [宋體][simsun.ttc]   [黑體][simhei.ttf]
     */
    private String font;

    /**
     * 須要傳入的數據
     */
    private Map<String, Object> dateMap;

    /**
     * 申請單號
     */
    private String applyFromCode;

    //上傳的目錄
    /*private static String directory;*/

    public GeneratePdf() {
    }

    public GeneratePdf(Map<String, Object> dateMap, String applyFromCode, String webPath) {
        this.dateMap = dateMap;
        this.applyFromCode = applyFromCode;
        this.webPath = webPath;
        this.templatePath = webPath + "/uf/template/";
        this.font = templatePath + "/simsun/simsun.ttc";
    }


    /**
     * 建立pdf
     *
     * @param data          變量數據
     * @param applyFromCode 新pdf地址 (一個單號只能有一個PDF文件,因此就直接用申請單號來命名)
     * @throws Exception
     */
    public Map<String, Object> createPdf(Map<String, Object> data, String applyFromCode) {
        Map<String, Object> map = new HashMap<>();
        String message = "";
        String detail = "";
        Boolean status = true;
        String code = "200";
        try {
            //建立文件
            //生成的pdf文件路徑
            String newPdfPath = webPath + imagePath + applyFromCode + ".pdf";
//            String newPdfPath = webPath + Setting.APPLY_FROM_PDF_PATH + "/" + applyFromCode + ".pdf";
            File file = new File(newPdfPath);
            if (!file.getParentFile().exists()) {
                file.getParentFile().mkdirs();
            }
            FileOutputStream out = new FileOutputStream(file);
            GeneratePdf pdf = new GeneratePdf();
            pdf.createPDF(data, out);
            message = "建立成功";
            //建立完成後的pdf文件所在地址
            detail = newPdfPath;
            logger.info("建立基礎PDF完成");
            //線程休息
            Thread.sleep(1000);
            out.close();
            out.flush();
        } catch (Exception e) {
            e.printStackTrace();
            message = "建立pdf文件錯誤失敗";
            status = false;
            code = "5005";
            detail = "";
            logger.error("建立pdf文件錯誤" + e.getMessage());
        }
        map.put("status", status);
        map.put("message", message);
        map.put("detail", detail);
        map.put("code", code);
        return map;
    }

    /**
     * 根據模板生成pdf
     *
     * @param data 傳入到freemarker模板裏的數據
     * @param out  生成的pdf文件流
     */
    public void createPDF(Object data, OutputStream out) throws Exception {
        // 建立一個FreeMarker實例, 負責管理FreeMarker模板的Configuration實例
        Configuration cfg = new Configuration(Configuration.DEFAULT_INCOMPATIBLE_IMPROVEMENTS);
        // 指定FreeMarker模板文件的位置
        ITextRenderer renderer = new ITextRenderer();
        try {
            cfg.setDirectoryForTemplateLoading(new File(templatePath));

            // 設置 css中 的字體樣式(暫時僅支持宋體和黑體)
            renderer.getFontResolver().addFont(font, BaseFont.IDENTITY_H, BaseFont.NOT_EMBEDDED);
            // 設置模板的編碼格式
            cfg.setEncoding(Locale.CHINA, encoding);
            // 獲取模板文件 template.ftl
            Template template = cfg.getTemplate(templateFileName, encoding);
            StringWriter writer = new StringWriter();
            // 將數據輸出到html中
            template.process(data, writer);
            writer.flush();
            String html = writer.toString();

            // 把html代碼傳入渲染器中
            renderer.setDocumentFromString(html);
            // 解決圖片的相對路徑問題 ##必須在設置document後再設置圖片路徑,否則不起做用
            // 若是使用絕對路徑依然有問題,能夠在路徑前面加"file:/"
            renderer.layout();
            renderer.createPDF(out, false);
            renderer.finishPDF();
            out.close();
            out.flush();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            out.close();
        }
    }

    @Override
    public void run() {
        logger.info("開始異步生成PDF文件");
        createPdf(dateMap, applyFromCode);
        logger.info("異步生成PDF文件完成");
    }

    public String getApplyFromCode() {
        return applyFromCode;
    }

    public void setApplyFromCode(String applyFromCode) {
        this.applyFromCode = applyFromCode;
    }
}

 

四、方法調用web

/***
     * Pdf sftp上傳服務器
     * @param name 申請人名字
     * @param idCardNo 申請人身份證號
     * @param dateD 申請時間
     * @param content 內容說明
     * @param applyFromCode 申請單號
     * @paramdirectory 服務器存儲路徑
     */
    public static void printPdf(String webPath, String name, String idCardNo, String dateD, String content, String applyFromCode) {
        HashMap<String, Object> map = new HashMap<String, Object>();
        map.put("name", name);
        map.put("idCardNo", idCardNo);
        map.put("dateD", dateD);
        map.put("content", content);

        GeneratePdf s = new GeneratePdf(map, applyFromCode, webPath);
        s.run();
    }
相關文章
相關標籤/搜索