html转pdf

最近工作需要将html转pdf,各种百度各种查资料,锁定用IText相关包,但是这个Itext包改动太大,包的关联真的乱出翔,每个版本都不一样,很容易导致包的问题然后报错,这里整理了一套亲测有用的,记个笔记

包:flying-saucer-core-9.1.16.jar,flying-saucer-pdf-itext5-9.1.16.jar,itextpdf-5.5.11.jar,

flying-saucer-pdf-itext5-9.1.16-sources.jar(这个可以不要),

下载 :https://download.csdn.net/download/hq091117/10755143

暂时就这几个包,从maven上看应该是最新的,

 

代码是参考网上的(这个亲测不行,没用,但是留着

package com.study.webapp.test;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.OutputStream;

import org.xhtmlrenderer.pdf.ITextFontResolver;
import org.xhtmlrenderer.pdf.ITextRenderer;

import com.itextpdf.text.pdf.BaseFont;

//注意包的引入

public class HtmlToPdf {

    /**
     * 将HTML转成PD格式的文件。html文件的格式比较严格
     * 
     * @param htmlFile
     * @param pdfFile
     * @throws Exception
     */
    public static void htmlToPdf(String htmlFile, String pdfFile) throws Exception {

        String url = new File(htmlFile).toURI().toURL().toString();
        System.out.println(url);

        OutputStream os = new FileOutputStream(pdfFile);
        ITextRenderer renderer = new ITextRenderer();
        renderer.setDocument(url);

        // step 3 解决中文支持
        ITextFontResolver fontResolver = renderer.getFontResolver();
        if ("linux".equals(getCurrentOperatingSystem())) {
            fontResolver.addFont("/usr/share/fonts/chiness/simsun.ttc", BaseFont.IDENTITY_H, BaseFont.EMBEDDED);
        } else {
            fontResolver.addFont("c:/Windows/Fonts/simsunb.ttf", BaseFont.IDENTITY_H, BaseFont.NOT_EMBEDDED);
        }

        renderer.layout();
        renderer.createPDF(os);
        os.close();

        System.out.println("create pdf done!!");

    }

    public static String getCurrentOperatingSystem() {
        String os = System.getProperty("os.name").toLowerCase();
        System.out.println("---------当前操作系统是-----------" + os);
        return os;
    }

    public static void main(String[] args) {
        String htmlFile = "d:/login.html";
        String pdfFile = "d:/login.pdf";
        try {
            HtmlToPdf.htmlToPdf(htmlFile, pdfFile);
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

}
这个方法后证明导出的pdf文件不能显示中文,而且排版有乱,试了很多套架包都不行,谁知道原因请分享一下

第二种方法:这个方法试过多次都是可以的,

参考网址:https://blog.csdn.net/accountwcx/article/details/46785437

这个方法就是需要借助别人的程序,windows上是需要执行exe程序,需要在官网(https://wkhtmltopdf.org/downloads.html)下载软件,然后在本地安装,官网上提供了windows和linux和macOS的安装程序,安装好之后只需要用代码去执行这个程序就行,而且可以直接用命令去执行这个程序,

windows上:c:\wkhtmltopdf.exe https://blog.csdn.net/hq091117 c:\csdn.pdf

代码执行:

package com.test;

import java.io.File;

public class HtmlToPdf {

    // wkhtmltopdf在系统中的路径
    private static final String toPdfTool = "F:\\wkhtmltopdf\\bin\\wkhtmltopdf.exe";

    private static final String toPdfLunix = "wkhtmltopdf";

    /**
     * html转pdf
     * 
     * @param srcPath
     *            html路径,可以是硬盘上的路径,也可以是网络路径
     * @param destPath
     *            pdf保存路径
     * @return 转换成功返回true
     */
    public static boolean convert(String srcPath, String destPath) {
        File file = new File(destPath);
        File parent = file.getParentFile();
        // 如果pdf保存路径不存在,则创建路径
        if (!parent.exists()) {
            parent.mkdirs();
        }
        String exe = "";
        if ("linux".equals(getCurrentOperatingSystem())) {
            exe = toPdfLunix;
        } else {
            exe = toPdfTool;
        }

        StringBuilder cmd = new StringBuilder();
        cmd.append(exe);
        cmd.append(" ");
        cmd.append(srcPath);
        cmd.append(" ");
        cmd.append(destPath);

        boolean result = true;
        try {
            Process proc = Runtime.getRuntime().exec(cmd.toString());
            HtmlToPdfInterceptor error = new HtmlToPdfInterceptor(proc.getErrorStream());
            HtmlToPdfInterceptor output = new HtmlToPdfInterceptor(proc.getInputStream());
            error.start();
            output.start();
            proc.waitFor();
        } catch (Exception e) {
            result = false;
            e.printStackTrace();
        }

        return result;
    }

    public static String getCurrentOperatingSystem() {
        String os = System.getProperty("os.name").toLowerCase();
        System.out.println("---------当前操作系统是-----------" + os);
        return os;
    }

    public static void main(String[] args) {
        String htmlFile = "/opt/topdf.html";
        String pdfFile = "/opt/topdf.pdf";
        try {
            boolean flag = HtmlToPdf.convert(htmlFile, pdfFile);
            System.out.println(flag);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

}
 

 

package com.test;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;

public class HtmlToPdfInterceptor extends Thread {
    private InputStream is;

    public HtmlToPdfInterceptor(InputStream is) {
        this.is = is;
    }

    public void run() {
        try {
            InputStreamReader isr = new InputStreamReader(is, "utf-8");
            BufferedReader br = new BufferedReader(isr);
            String line = null;
            while ((line = br.readLine()) != null) {
                // System.out.println(line.toString()); // 输出内容
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

}
 

 

然后我也在linux上也执行过,有用

linux上:

我先是新建一个java程序 ,然后把java程序打包成一个jar的包,在执行jar包的main方法

第三种方法亲测有效

架包下载:https://download.csdn.net/download/hq091117/10782558

FreemarkerConfiguration 类:

package com.zh.audit.confirmation.htmltopdf;

import freemarker.template.Configuration;

public class FreemarkerConfiguration {

    private static Configuration config = null;

    static {
        config = new Configuration();
        config.setClassForTemplateLoading(FreemarkerConfiguration.class, "/template");
    }

    public static Configuration getConfiguation() {
        return config;
    }

}
TemplateUtils 类:

package com.zh.audit.confirmation.htmltopdf;

import java.io.FileOutputStream;
import java.io.OutputStream;
import java.util.HashMap;
import java.util.Map;

import org.springframework.ui.freemarker.FreeMarkerTemplateUtils;

import freemarker.template.Configuration;
import freemarker.template.Template;

/**
 * 
 * 通用 工具类
 *
 */
public class TemplateUtils {

    public static String getTranslateTemplate(String path, Map<String, Object> model) throws Exception {
        String content = null;

        Configuration config = FreemarkerConfiguration.getConfiguation();
        config.setDefaultEncoding("UTF-8");
        Template template = config.getTemplate(path);
        content = FreeMarkerTemplateUtils.processTemplateIntoString(template, model);
        // StringWriter stringWriter = new StringWriter();
        // BufferedWriter writer = new BufferedWriter(stringWriter);
        // template.setEncoding("UTF-8");
        // template.process(model, writer);
        // content = stringWriter.toString();
        // writer.flush();
        // writer.close();
        return content;
    }

    public static void main(String[] args) throws Exception {
        OutputStream out = new FileOutputStream("d:/topdf.pdf");
        try {
            String c = getTranslateTemplate("topdf2.html", new HashMap<String, Object>(0));
            // System.out.println(c);
            new PdfGenerator().generate(c, out);
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }

}
以上两个类是用于读取html内容的,架包是:freemarker-2.3.20.jar

PdfGenerator(这个是开始转pdf的):

架包:flying-saucer-core-9.1.7.jar,flying-saucer-pdf-itext5-9.1.7.jar,itext-asian-5.2.0.jar,itextpdf-5.5.1.jar,spring-test-4.3.7.RELEASE.jar,xmlworker-5.5.1.jar

package com.zh.audit.confirmation.htmltopdf;

import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.nio.charset.Charset;

import org.apache.commons.lang3.StringUtils;

import com.itextpdf.text.Document;
import com.itextpdf.text.DocumentException;
import com.itextpdf.text.Font;
import com.itextpdf.text.Image;
import com.itextpdf.text.PageSize;
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.exceptions.CssResolverException;
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.AbstractImageProvider;
import com.itextpdf.tool.xml.pipeline.html.HtmlPipeline;
import com.itextpdf.tool.xml.pipeline.html.HtmlPipelineContext;
import com.itextpdf.tool.xml.pipeline.html.ImageProvider;
import com.itextpdf.tool.xml.pipeline.html.NoImageProviderException;

public class PdfGenerator {

    private static final String CHARSET_NAME = "UTF-8";

    public void generate(String htmlStr, OutputStream out) throws IOException, DocumentException, CssResolverException {

        Document document = new Document(PageSize.A4, 30, 30, 30, 30);
        document.setMargins(30, 30, 30, 30);
        PdfWriter writer = PdfWriter.getInstance(document, out);
        document.open();

        // html内容解析
        HtmlPipelineContext htmlContext = new HtmlPipelineContext(new CssAppliersImpl(new XMLWorkerFontProvider() {
            @Override
            public Font getFont(String fontName, String encoding, float size, final int style) {
                Font font = null;
                if (fontName == null || "宋体".equals(fontName) || "simsun".equals(fontName)) {
                    // 字体
                    String fontCn = getSIMSUNFont();
                    BaseFont bf;
                    try {
                        // 注意这里有一个,1
                        bf = BaseFont.createFont(fontCn + ",1", BaseFont.IDENTITY_H, BaseFont.NOT_EMBEDDED);
                        font = new Font(bf, size, style);
                    } catch (DocumentException e) {
                        e.printStackTrace();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }

                }
                return font;
            }
        })) {
            @Override
            public HtmlPipelineContext clone() throws CloneNotSupportedException {
                HtmlPipelineContext context = super.clone();
                try {
                    ImageProvider imageProvider = this.getImageProvider();
                    context.setImageProvider(imageProvider);
                } catch (NoImageProviderException e) {
                }
                return context;
            }
        };

        // 图片解析
        htmlContext.setImageProvider(new AbstractImageProvider() {

            // String rootPath = servletContext.getRealPath("/");

            @Override
            public String getImageRootPath() {
                return "";
            }

            @Override
            public Image retrieve(String src) {
                if (StringUtils.isEmpty(src)) {
                    return null;
                }
                try {
                    // String imageFilePath = new File(rootPath,
                    // src).toURI().toString();
                    Image image = Image.getInstance(src);
                    image.setAbsolutePosition(400, 400);
                    if (image != null) {
                        store(src, image);
                        return image;
                    }
                } catch (Throwable e) {
                    e.printStackTrace();
                }
                return super.retrieve(src);
            }
        });
        htmlContext.setAcceptUnknown(true).autoBookmark(true).setTagFactory(Tags.getHtmlTagProcessorFactory());

        // css解析
        CSSResolver cssResolver = XMLWorkerHelper.getInstance().getDefaultCssResolver(true);
        cssResolver.setFileRetrieve(new FileRetrieve() {
            @Override
            public void processFromStream(InputStream in, ReadingProcessor processor) {
                try {
                    InputStreamReader reader = new InputStreamReader(in, CHARSET_NAME);
                    int i = -1;
                    while (-1 != (i = reader.read())) {
                        processor.process(i);
                    }
                } catch (Throwable e) {

                }
            }

            // 解析href
            @Override
            public void processFromHref(String href, ReadingProcessor processor) throws IOException {
                URL url = new URL(href);
                HttpURLConnection conn = (HttpURLConnection) url.openConnection();
                conn.setRequestMethod("GET");
                conn.setConnectTimeout(5 * 1000);
                InputStream is = conn.getInputStream();
                InputStreamReader reader = new InputStreamReader(is, CHARSET_NAME);
                try {
                    int i = -1;
                    while (-1 != (i = reader.read())) {
                        processor.process(i);
                    }
                } catch (Throwable e) {
                    e.printStackTrace();
                }
            }
        });
        // cssResolver.addCss(".div-0{font-size: 36px; text-align:
        // center;}",true);
        HtmlPipeline htmlPipeline = new HtmlPipeline(htmlContext, new PdfWriterPipeline(document, writer));
        Pipeline<?> pipeline = new CssResolverPipeline(cssResolver, htmlPipeline);
        XMLWorker worker = new XMLWorker(pipeline, true);
        XMLParser parser = new XMLParser(true, worker, Charset.forName(CHARSET_NAME));
        InputStream inputStream = new ByteArrayInputStream(htmlStr.getBytes(CHARSET_NAME));
        try {
            parser.parse(inputStream, Charset.forName(CHARSET_NAME));
        } catch (Throwable e) {
            e.printStackTrace();
        }
        document.close();
    }

    /**
     * 获取中文字体位置
     *
     * @return
     */
    private String getSIMSUNFont() {

        String font = this.getClass().getResource("/").getPath() + "template/SIMSUN.TTC";
        // String font = "D:/tmp/SIMSUN.TTC";
        // System.out.println(font);
        if (!new File(font).exists()) {
            throw new RuntimeException("字体文件不存在,影响导出pdf中文显示!" + font);
        }

        return font;
    }
}

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值