使用itext将html页面转pdf(完美支持中文)

  |   3 评论   |   1,720 浏览

最近有用到使用itext将html页面转pdf的操作,做个笔记

技术预研

受限于某些外部原因(该环境无法使用java执行sh脚本),wkhtmltopdf被排除在外,最终选择了itext全家桶,itextpdf作为pdf生成核心,xmlworker用于html转pdf,itext-asian用于支持中文显示,视情况而定还可以引入nekohtml对非标准html页面进行标签补全.

引入maven依赖

        <dependency>
            <groupId>com.itextpdf</groupId>
            <artifactId>itextpdf</artifactId>
            <version>5.5.11</version>
        </dependency>
        <dependency>
            <groupId>com.itextpdf.tool</groupId>
            <artifactId>xmlworker</artifactId>
            <version>5.5.11</version>
        </dependency>
        <dependency>
            <groupId>com.itextpdf</groupId>
            <artifactId>itext-asian</artifactId>
            <version>5.2.0</version>
        </dependency>

核心功能代码

import com.itextpdf.text.Document;
import com.itextpdf.text.Font;
import com.itextpdf.text.PageSize;
import com.itextpdf.text.pdf.BaseFont;
import com.itextpdf.text.pdf.PdfWriter;
import com.itextpdf.tool.xml.XMLWorkerFontProvider;
import com.itextpdf.tool.xml.XMLWorkerHelper;

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

public class PDFUtil {
    public static void writeStringToOutputStreamAsPDF(String html, OutputStream os) {
        writeToOutputStreamAsPDF(new ByteArrayInputStream(html.getBytes()), os);
    }

    public static void writeToOutputStreamAsPDF(InputStream html, OutputStream os) {
        try {
            Document document = new Document(PageSize.A4);
            PdfWriter pdfWriter = PdfWriter.getInstance(document, os);
            document.open();
            XMLWorkerHelper worker = XMLWorkerHelper.getInstance();
            worker.parseXHtml(pdfWriter, document, html, Charset.forName("UTF-8"), new AsianFontProvider());
            document.close();
        } catch (Exception e) {
        }
    }
}
/**
 * 用于中文显示的Provider
 */
class AsianFontProvider extends XMLWorkerFontProvider {
    @Override
    public Font getFont(final String fontname, String encoding, float size, final int style) {
        try {
            BaseFont bfChinese = BaseFont.createFont("STSongStd-Light", "UniGB-UCS2-H", BaseFont.NOT_EMBEDDED);
            return new Font(bfChinese, size, style);
        } catch (Exception e) {
        }
        return super.getFont(fontname, encoding, size, style);
    }
}

其中writeToOutputStreamAsPDF方法接受输入流形式的html文件,然后将pdf写入到输出流中,而writeStringToOutputStreamAsPDF方法则接受文本形式的html文件,方便做一些模板替换的预处理工作,当然也可以结合vm,fm等模板引擎进行模板文件数据渲染,请自行了解,OutputStream输出流可作为文件输出流写入到生成PDF文件,也可以作为web环境下的response提供PDF文档显示/下载功能

评论

  • lumang 回复»

    QQ20180828165317png
    我使用的也是这个,但是两次发现不一致,pdf用别之前打开也是草体的

  • alanfans 回复»

    BaseFont.createFont(“STSongStd-Light”, “UniGB-UCS2-H”
    这个应该可以 改字体吧

  • lumang 回复»

    老哥我想问一下我使用的字体和您相同但是在浏览器预览的PDF和pdf转成的图片字体显示不同,老哥有遇到吗?

    QQ20180828155743png

    QQ20180828155910png

发表评论

validate