使用 flying-saucer-pdf 实现html转换pdf

ps:之前研究了使用itext html转PDF 对中文和css的支持不很好,果然Google了一把,发现flying-saucer-pdf这个效果好,研究了一下果然行,运用到项目中基本上能满足需求。

1、pom.xml 文件 

 1  1   <dependency>
 2  2             <groupId>com.itextpdf</groupId>
 3  3             <artifactId>itextpdf</artifactId>
 4  4             <version>5.5.13</version>
 5  5         </dependency>
 6  6         <dependency>
 7  7             <groupId>com.itextpdf.tool</groupId>
 8  8             <artifactId>xmlworker</artifactId>
 9  9             <version>5.5.13</version>
10 10         </dependency>
11 11         <dependency>
12 12             <groupId>com.itextpdf</groupId>
13 13             <artifactId>itext-asian</artifactId>
14 14             <version>5.2.0</version>
15 15         </dependency>
16 16         <dependency>
17 17             <groupId>org.xhtmlrenderer</groupId>
18 18             <artifactId>flying-saucer-pdf</artifactId>
19 19             <version>9.0.3</version>
20 20         </dependency>

2、代码

package pdf.kit;

import com.itextpdf.text.*;
import com.itextpdf.text.pdf.BaseFont;
import com.itextpdf.text.pdf.PdfWriter;
import com.itextpdf.tool.xml.Pipeline;
import com.itextpdf.tool.xml.XMLWorker;
import com.itextpdf.tool.xml.XMLWorkerFontProvider;
import com.itextpdf.tool.xml.XMLWorkerHelper;
import com.itextpdf.tool.xml.html.CssAppliers;
import com.itextpdf.tool.xml.html.CssAppliersImpl;
import com.itextpdf.tool.xml.html.Tags;
import com.itextpdf.tool.xml.net.FileRetrieve;
import com.itextpdf.tool.xml.net.ReadingProcessor;
import com.itextpdf.tool.xml.parser.XMLParser;
import com.itextpdf.tool.xml.pipeline.css.CSSResolver;
import com.itextpdf.tool.xml.pipeline.css.CssResolverPipeline;
import com.itextpdf.tool.xml.pipeline.end.PdfWriterPipeline;
import com.itextpdf.tool.xml.pipeline.html.*;
import org.apache.commons.io.FileUtils;
import org.apache.commons.lang.StringUtils;
import org.xhtmlrenderer.pdf.ITextFontResolver;
import org.xhtmlrenderer.pdf.ITextRenderer;

import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;
import java.nio.charset.Charset;

/**
 * html 转换成 pdf
 */
public class ParseHtmlTable {

    public static final String pdfDestPath = "C:/Users/xxx-b/Desktop/pdf/";
    public static final String htmlPath = "D:\\3-workspace\\pdf-test\\src\\test\\resources\\templates\\test.html";

    public static void main(String[] args) throws IOException, DocumentException {
        String pdfName = "test.pdf";
        ParseHtmlTable parseHtmlTable = new ParseHtmlTable();
        String htmlStr = FileUtils.readFileToString(new File(htmlPath));
        parseHtmlTable.html2pdf(htmlStr,pdfName ,"C:\\Windows\\Fonts");
    }


    public void html2pdf(String html, String pdfName, String fontDir) {
        try {
            ByteArrayOutputStream os = new ByteArrayOutputStream();
            ITextRenderer renderer = new ITextRenderer();
            ITextFontResolver fontResolver = (ITextFontResolver) renderer.getSharedContext().getFontResolver();
            //添加字体库 begin
            File f = new File(fontDir);
            if (f.isDirectory()) {
                File[] files = f.listFiles(new FilenameFilter() {
                    public boolean accept(File dir, String name) {
                        String lower = name.toLowerCase();
                        return lower.endsWith(".otf") || lower.endsWith(".ttf") || lower.endsWith(".ttc");
                    }
                });
                for (int i = 0; i < files.length; i++) {
                    fontResolver.addFont(files[i].getAbsolutePath(), BaseFont.IDENTITY_H, BaseFont.NOT_EMBEDDED);
                }
            }
            //添加字体库end
            renderer.setDocumentFromString(html);
            renderer.layout();
            renderer.createPDF(os);
            renderer.finishPDF();
            byte[] buff = os.toByteArray();
            //保存到磁盘上
            FileUtil.byte2File(buff,pdfDestPath,pdfName);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}


FileUtil.java

package pdf.kit;

import java.io.*;

public class FileUtil {

    /**
     * 获得指定文件的byte数组
     *
     * @param filePath 文件绝对路径
     * @return
     */
    public static byte[] file2Byte(String filePath) {
        ByteArrayOutputStream bos = null;
        BufferedInputStream in = null;
        try {
            File file = new File(filePath);
            if (!file.exists()) {
                throw new FileNotFoundException("file not exists");
            }
            bos = new ByteArrayOutputStream((int) file.length());
            in = new BufferedInputStream(new FileInputStream(file));
            int buf_size = 1024;
            byte[] buffer = new byte[buf_size];
            int len = 0;
            while (-1 != (len = in.read(buffer, 0, buf_size))) {
                bos.write(buffer, 0, len);
            }
            return bos.toByteArray();
        } catch (Exception e) {
            System.out.println(e.getMessage());
            e.printStackTrace();
            return null;
        } finally {
            try {
                if (in != null) {
                    in.close();
                }
                if (bos != null) {
                    bos.close();
                }
            } catch (Exception e) {
                System.out.println(e.getMessage());
                e.printStackTrace();
            }
        }
    }

    /**
     * 根据byte数组,生成文件
     *
     * @param bfile    文件数组
     * @param filePath 文件存放路径
     * @param fileName 文件名称
     */
    public static void byte2File(byte[] bfile, String filePath, String fileName) {
        BufferedOutputStream bos = null;
        FileOutputStream fos = null;
        File file = null;
        try {
            File dir = new File(filePath);
            if (!dir.exists() && !dir.isDirectory()) {//判断文件目录是否存在
                dir.mkdirs();
            }
            file = new File(filePath + fileName);
            fos = new FileOutputStream(file);
            bos = new BufferedOutputStream(fos);
            bos.write(bfile);
        } catch (Exception e) {
            System.out.println(e.getMessage());
            e.printStackTrace();
        } finally {
            try {
                if (bos != null) {
                    bos.close();
                }
                if (fos != null) {
                    fos.close();
                }
            } catch (Exception e) {
                System.out.println(e.getMessage());
                e.printStackTrace();
            }

        }
    }

}

3.html

 
 
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html>
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
    <style type="text/css">

        *{
            padding: 0;
            margin: 0;
            color: #000;
            font-family:Microsoft YaHei
        }
    </style>
</head>
<body screen_capture_injected="true" ryt11773="1">
<p>
    <span style="font-size:12.0pt; font-family:MS Mincho">長空</span> <span
        style="font-size:12.0pt; font-family:Times New Roman,serif">(Broken
            Sword),</span> <span style="font-size:12.0pt; font-family:MS Mincho">秦王殘劍</span>
    <span style="font-size:12.0pt; font-family:Times New Roman,serif">(Flying
            Snow),</span> <span style="font-size:12.0pt; font-family:MS Mincho">飛雪</span>
    <span style="font-size:12.0pt; font-family:Times New Roman,serif">(Moon),
        </span> <span style="font-size:12.0pt; font-family:MS Mincho">如月</span> <span
        style="font-size:12.0pt; font-family:Times New Roman,serif">(the
            King), and</span> <span style="font-size:12.0pt; font-family:MS Mincho">秦王</span>
    <span style="font-size:12.0pt; font-family:Times New Roman,serif">(Sky).</span>
</p>
<p>选中<input type="checkbox" value="1" disabled="disabled" checked="checked"/></p>
<br/>
<textarea rows="11" cols="10"  disabled="disabled">
    adfadfadfadfa
</textarea>
</body>
</html>
 
  
 
 

4、pdf结果

 

5、一些总结

   1、模板的要求: html的格式要求符合xml格式,必须要有闭合标签。

   2、字体的支持: font-family:Microsoft YaHei ,html中定义字体,程序中一定要导入想匹配的格式,才能有效。

猜你喜欢

转载自www.cnblogs.com/dongjingzhiai/p/9018956.html
今日推荐