HTML轉PDF


Maven依賴

<dependency>
    <groupId>com.itextpdf</groupId>
    <artifactId>itextpdf</artifactId>
    <version>5.5.7</version>
</dependency>
<dependency>
    <groupId>com.itextpdf.tool</groupId>
    <artifactId>xmlworker</artifactId>
    <version>5.5.7</version>
</dependency>

類圖及API

類圖

IHtml2PdfService

HTML轉PDF的服務接口

write (htmlContent: java.lang.String, os: java.io.OutputStream): void

將指定的html轉換成pdf內容后,寫到指定的輸出流。

Html2PdfServiceImpl

HTML轉PDF的服務實現類

write (htmlContent: java.lang.String, os: java.io.OutputStream): void

實現:將指定的html轉換成pdf內容后,寫到指定的輸出流。

getIntaceHtml (htmlContent: String): String

私有方法,用於獲取完整的html文檔;如果傳入的只是html片斷,需要使用模板將其完整化。

doWrite (htmlContent: String, os: OutputStream): void

私有方法,將完整的html文檔轉換成pdf之后,寫到指定的輸出流。

代碼

IHtml2PdfService

package cn.ljl.javaweb.demo.ckeditor.service;

public interface IHtml2PdfService {
    /** html完整內容的前綴標識 */
    public static final String INTACT_FLAG = "<html>";
    
    /**
     * html模板,當待轉換的html只是片斷時,需將其插入到模板的body內.
     */
    public static final String TEMPLATE_HTML = 
            "<html>" +
            "    <head>" +
            "        <style type='text/css'>body {font-family: SimSun;}</style>" +
            "    </head>" +
            "    <body>" +
            "        ${content}" +
            "    </body>" +
            "</html>";
    
    /** 將指定的html內容轉化成pdf文檔之后,寫入到指定的輸出流. */
    public void write(java.lang.String htmlContent, java.io.OutputStream os);
    
}

Html2PdfServiceImpl

package cn.ljl.javaweb.demo.ckeditor.service;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.nio.charset.Charset;

import com.itextpdf.text.DocumentException;

public class Html2PdfServiceImpl implements IHtml2PdfService {
    @Override
    public void write(String htmlContent, OutputStream os) {
        if (htmlContent == null || htmlContent.length() == 0)
            return;

        if (os == null)
            return;

        htmlContent = getIntaceHtml(htmlContent);
        doWrite(htmlContent, os);
    }
    
    /**
     * 根據提供的html內容,獲取完整的html內容.<br>
     * @param htmlContent
     * @return
     */
    private String getIntaceHtml(String htmlContent) {
        boolean intact = htmlContent.trim().toLowerCase()
                .startsWith(INTACT_FLAG);
        if (!intact) {
            htmlContent = TEMPLATE_HTML.replaceFirst("\\$\\{content\\}", htmlContent);
        }

        return htmlContent;
    }
    
    /**
     * 實施寫操作.<br>
     * @param htmlContent
     * @param os
     */
    private void doWrite(String htmlContent, OutputStream os) {
        InputStream is = new ByteArrayInputStream(htmlContent.getBytes());

        com.itextpdf.text.Document document = new com.itextpdf.text.Document();
        com.itextpdf.text.pdf.PdfWriter writer = null;
        try {
            writer = com.itextpdf.text.pdf.PdfWriter
                    .getInstance(document, os);
            document.open();
            
            com.itextpdf.tool.xml.XMLWorkerHelper.getInstance().parseXHtml(writer,
                    document, is, Charset.forName("gbk"));
        } catch (DocumentException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        
        writer.flush();
        // SINOBEST HTML2PDF 如果我們調用writer.close(),可能無法正常的生成pdf,甚至會遇到
        // Exception:The page 1 was requested but the document has only 0 pages.
        // writer.close();
        document.close();
    }
}

可能遇到的問題

1. 中文字符顯示問題

如果是完整的html文檔,需要使用css為整個文檔設置一個默認的字體,如IHtml2PdfService的模板中的代碼片段:

<style type='text/css'>body {font-family: SimSun;}</style>

2. 部分內容空白

可能是html文檔使用了服務器中沒有的字體。比如html文檔的某個div,設置了仿宋字體,而機器上又沒有安裝,那么轉換成pdf的時候,對應的內容是空白。


免責聲明!

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



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