freemarket+itext+springboot將html靜態頁面渲染后導出為pdf文件


 

1、maven依賴

       <dependency>
            <groupId>com.itextpdf</groupId>
            <artifactId>itextpdf</artifactId>
            <version>5.4.2</version>
        </dependency>
 
        <dependency>
            <groupId>org.xhtmlrenderer</groupId>
            <artifactId>core-renderer</artifactId>
            <version>R8</version>
        </dependency>
        <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-io</artifactId>
            <version>1.3.2</version>

    </dependency>

 

2、controller

@RequestMapping(value = "projectExport", method = RequestMethod.GET)
    public void projectExport(HttpServletRequest request, HttpServletResponse response) {
        try {
            
            Map map=new HashMap<String,Object>();
            map.put("test","測試");
           
            ByteArrayOutputStream baos = PDFUtil.createPDF("templates/project.html", map);
            //設置response文件頭
          
            PDFUtil.renderPdf(response, baos.toByteArray(), "pdf文件");
            baos.close();
        } catch (Exception e) {
            logger.info("導出報錯",e);
        }
    }
3、PDFUtil

import com.itextpdf.text.pdf.BaseFont;
import freemarker.template.Configuration;
import freemarker.template.Template;
import org.apache.commons.io.output.ByteArrayOutputStream;
import org.apache.commons.lang.StringUtils;
import org.xhtmlrenderer.pdf.ITextFontResolver;
import org.xhtmlrenderer.pdf.ITextRenderer;
 
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.util.Locale;
 
 
/**
 * PDF工具類
 * @author LQX
 *
 */
public class PDFUtil {
 
    private static String DEFAULT_ENCODING="utf-8";
    private static String PDF_TYPE="application/pdf";
    private static boolean DEFAULT_NOCACHE=true;
    private static String HEADER_ENCODING="utf-8";
    private static String HEADER_NOCACHE="no-cache";
 
    /**
     * 生成PDF文件流
     * @param ftlName 文件名稱
     * @param root    數據
     * @return ByteArrayOutputStream
     * @throws Exception
     */
    public static ByteArrayOutputStream createPDF(String ftlName, Object root) throws Exception {
        //相對路徑
        File file = new File(PDFUtil.class.getResource("/").getPath());
        Configuration cfg = new Configuration();
        try {
            cfg.setLocale(Locale.CHINA);
            cfg.setEncoding(Locale.CHINA, "UTF-8");
            //設置編碼
            cfg.setDefaultEncoding("UTF-8");
            //設置模板路徑
            cfg.setDirectoryForTemplateLoading(file);
            //獲取模板
            Template template = cfg.getTemplate(ftlName);
            template.setEncoding("UTF-8");
            ITextRenderer iTextRenderer = new ITextRenderer();
            //設置字體
            ITextFontResolver fontResolver = iTextRenderer.getFontResolver();
            fontResolver.addFont(file.getPath() + "/public/font/simsun.ttf", BaseFont.IDENTITY_H, BaseFont.NOT_EMBEDDED);
            Writer writer = new StringWriter();
            //數據填充模板
            template.process(root, writer);
            //設置輸出文件內容及路徑
            String str = writer.toString();
            iTextRenderer.setDocumentFromString(str);
            /*iTextRenderer.getSharedContext().setBaseURL("");//共享路徑*/
            iTextRenderer.layout();
            //生成PDF
            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            iTextRenderer.createPDF(baos);
            baos.close();
            return baos;
        } catch(Exception e) {
            throw new Exception(e);
        }
    }
    public static void renderPdf(HttpServletResponse response, final byte[] bytes, final String filename) {
        initResponseHeader(response, PDF_TYPE);
        setFileDownloadHeader(response, filename, ".pdf");
        if (null != bytes) {
            try {
                response.getOutputStream().write(bytes);
                response.getOutputStream().flush();
            } catch (IOException e) {
                throw new IllegalArgumentException(e);
            }
        }
    }
 
    /**
     * 分析並設置contentType與headers.
     */
    private static HttpServletResponse initResponseHeader(HttpServletResponse response, final String contentType, final String... headers) {
        // 分析headers參數
        String encoding = DEFAULT_ENCODING;
        boolean noCache = DEFAULT_NOCACHE;
        for (String header : headers) {
            String headerName = StringUtils.substringBefore(header, ":");
            String headerValue = StringUtils.substringAfter(header, ":");
            if (StringUtils.equalsIgnoreCase(headerName, HEADER_ENCODING)) {
                encoding = headerValue;
            } else if (StringUtils.equalsIgnoreCase(headerName, HEADER_NOCACHE)) {
                noCache = Boolean.parseBoolean(headerValue);
            } else {
                throw new IllegalArgumentException(headerName + "不是一個合法的header類型");
            }
        }
        // 設置headers參數
        String fullContentType = contentType + ";charset=" + encoding;
        response.setContentType(fullContentType);
        if (noCache) {
            // Http 1.0 header
            response.setDateHeader("Expires", 0);
            response.addHeader("Pragma", "no-cache");
            // Http 1.1 header
            response.setHeader("Cache-Control", "no-cache");
        }
        return response;
    }
 
    /**
     * 設置讓瀏覽器彈出下載對話框的Header.
     * @param
     */
    public static void setFileDownloadHeader(HttpServletResponse response, String fileName, String fileType) {
        try {
            // 中文文件名支持
            String encodedfileName = new String(fileName.getBytes("GBK"), "ISO8859-1");
            response.setHeader("Content-Disposition", "attachment; filename=\"" + encodedfileName + fileType + "\"");
        } catch (UnsupportedEncodingException e) {
        }
    }
}

3、project.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>PDF下載</title>  
        <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />  
        <style mce_bogus="1" type="text/css">  
            body {font-family: SimSun; }
            @page {size: 800mm 400mm}
        </style>
    </head>
    <body> 
        <table width="100%" height="60" border="0" align="center" cellpadding="0" cellspacing="0">
            <tr>
                <td>12345</td>
                <td>${test}</td>
                <td>abc</td>
            </tr>
        </table>
    </body>
</html>

 

 

需要注意的點:

(1)、中文字體

html中要將body標簽的字體設置為SimSun,然后項目中要放這個字體文件,因為服務器中通常沒有這個文件,simsun.ttf字體百度上都可以下載。只有設置了字體后html中的中文才能識別出來。

(2)、css文件

如果你想導的pdf文件的樣式是css渲染后的頁面樣式,一定要注意link中css引用的路徑,通常用服務器的絕對路徑,你也可以自己換一換路徑試試。導出時會因為一些外部的文件的路徑寫的不對而出現空指針異常,可以先把這些都注釋掉再調試。

(3)、html標簽

這個工具導出的時候對html標簽的要求比較的嚴格,比如一些閉合標簽一定要寫完整,href鏈接中直接請求接口帶參數的時候有&連接的時候要在&后面加上amp;

(4)、pdf文件的大小

給這個html文件加上css樣式@page {size:800mm 400mm}這個樣式可以調整pdf的文件,因為我導出的時候寬度達不到我想要的寬度,但是我還是不會動態的去設置這個大小,歡迎知道的小伙伴指教。
 ———————————————— 
原文鏈接:https://blog.csdn.net/haha_66666/article/details/83025919

 

 

 


免責聲明!

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



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