【原创】Java开发word模板转html导出pdf

使用iText5来导出pdf,具体操作步骤如下:
1、首先创建一个doc格式的word文档,转换为html格式

word模板转html链接地址在这里插入图片描述
2、替换要填充的内容,把html文件后缀改为ftl并放在resources/templates路径下,最后将字体(任何字体都可以)放在resources/font路径下
在这里插入图片描述
3、最后就是java代码

    <!-- https://mvnrepository.com/artifact/com.itextpdf/itextpdf -->
    <dependency>
      <groupId>com.itextpdf</groupId>
      <artifactId>itextpdf</artifactId>
      <version>5.5.10</version>
    </dependency>
    <dependency>
      <groupId>com.itextpdf.tool</groupId>
      <artifactId>xmlworker</artifactId>
      <version>5.5.13</version>
    </dependency>
    <!-- https://mvnrepository.com/artifact/org.jsoup/jsoup -->
    <dependency>
      <groupId>org.jsoup</groupId>
      <artifactId>jsoup</artifactId>
      <version>1.14.3</version>
    </dependency>
package com.catxcloud.purchase.util;

import com.catxcloud.core.exception.GenericException;
import com.itextpdf.text.*;
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 freemarker.template.Configuration;
import freemarker.template.Template;
import freemarker.template.TemplateExceptionHandler;
import freemarker.template.Version;
import org.apache.commons.lang3.StringUtils;
import org.jsoup.Jsoup;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.servlet.view.freemarker.FreeMarkerConfigurer;
import sun.misc.BASE64Decoder;

import java.io.*;
import java.nio.charset.Charset;
import java.util.Iterator;

/**
 * @packageName: com.emoon.utils
 * @className: PdfTool
 * @description: pdf工具类
 * @version: 1.0.0
 */
public class PdfTool {

    private static final Logger LOGGER = LoggerFactory.getLogger(PdfTool.class);

    /**
     * 默认的编码为utf-8
     */
    private static final String DEFAULT_ENCODING = "utf-8";
    /**
     * 参数错误码
     */
    private static final Integer PARAM_ERROR_CODE = 500001;
    /**
     * 参数错误描述
     */
    private static final String PARAM_ERROR_DESC = "参数有误!";

    /**
     * 生成html错误码
     */
    private static final Integer HTML_CREATE_ERROR_CODE = 500002;
    /**
     * html生成失败描述
     */
    private static final String HTML_CREATE_ERROR_DESC = "html生成失败";

    /**
     * html转pdf失败错误码
     */
    private static final Integer PARSE_HTML_TO_PDF_ERROR_CODE = 500003;
    /**
     * html转pdf失败描述
     */
    private static final String PARSE_HTML_TO_PDF_ERROR_DESC = "html转pdf失败";

    /**
     * PDF生成失败错误码
     */
    private static final Integer PDF_CREATE_ERROR_CODE = 500004;
    /**
     * PDF生成失败描述
     */
    private static final String PDF_CREATE_ERROR_DESC = "PDF生成失败";

    /**
     * word转pdf失败错误码
     */
    private static final Integer PARSE_WORD_TO_PDF_ERROR_CODE = 500005;
    /**
     * word转pdf失败描述
     */
    private static final String PARSE_WORD_TO_PDF_ERROR_DESC = "word转pdf失败";
    /**
     * 获取pdf签章hash失败错误码
     */
    private static final Integer GET_SIGN_HASH_ERROR_CODE = 500005;
    /**
     * 获取pdf签章hash失败的描述
     */
    private static final String GET_SIGN_HASH_ERROR_DESC = "获取pdf签章hash失败";

    /**
     * description:创建Configuration配置的方法
     * @param version            版本号
     * @param encoding           编码
     * @param ftlOrXmlParentPath ftl或者xml文件父路径地址
     * @param pathIsAP           ftl或者xml文件父路径地址是否是绝对路径,true-是,false-否
     * @return freemarker.template.Configuration Configuration配置对象
     */
    private static Configuration getConfiguration(Version version, String encoding,
                                                  String ftlOrXmlParentPath, boolean pathIsAP) throws IOException {
        //Configuration 用于读取ftl文件
        Configuration configuration = new Configuration(version);
        configuration.setDefaultEncoding(encoding);

        /**
         * 两种指定ftl文件所在目录路径的方式,注意这两种方式都是
         * 指定ftl文件所在目录的路径,而不是ftl文件的路径
         */
        //指定路径的第一种方式(根据某个类的相对路径指定)
        // configuration.setClassForTemplateLoading(this.getClass(), "");

        //指定路径的第二种方式
        // configuration.setDirectoryForTemplateLoading(new File(ftlOrXmlParentPath));

        //如果是绝对路径
        if (pathIsAP) {
            configuration.setDirectoryForTemplateLoading(new File(ftlOrXmlParentPath));
        } else {
            FreeMarkerConfigurer freeMarkerConfigurer = SpringBootBeanUtil.getBean(FreeMarkerConfigurer.class);
            configuration = freeMarkerConfigurer.getConfiguration();
            if (StringUtils.isNotBlank(ftlOrXmlParentPath)) {
                StringBuffer basePackagePath = new StringBuffer();
                //加载指定的模版文件夹
                if (ftlOrXmlParentPath.startsWith("/")) {
                    if (ftlOrXmlParentPath.endsWith("/")) {
                        basePackagePath.append(ftlOrXmlParentPath);
                    } else {
                        basePackagePath.append(ftlOrXmlParentPath);
                        basePackagePath.append("/");
                    }
                } else {
                    basePackagePath.append("/");
                    if (ftlOrXmlParentPath.endsWith("/")) {
                        basePackagePath.append(ftlOrXmlParentPath);
                    } else {
                        basePackagePath.append(ftlOrXmlParentPath);
                        basePackagePath.append("/");
                    }
                }
                configuration.setClassForTemplateLoading(PdfTool.class, basePackagePath.toString());
            }
        }

        return configuration;
    }

    /**
     * description: 根据html修改的ftl模版填入数据生成html的方法(如果模版是word,转成html编辑成ftl模版即可)
     * @param dataModel         数据模型
     * @param ftlParentPath     ftl文件的父路径,相对路径或者绝对路径,相对路径时指:相对classpath的路径,
     *                          可为空,当表示绝对父路径时必填,相对父路径时可不填,不填默认加载配置文件中的:
     *                          spring.freemarker.template-loader-path=classpath:/templates/ 的配置
     * @param ftlParentPathIsAP ftl文件的父路径是否是绝对路径,true--是,false-否
     * @param ftlTemplateName   ftl文件名称,需以.ftl结尾
     * @param outputStream      html文件输出流
     * @param encoding          编码,可为空,默认为:utf-8
     * @param versionCode       版本号,可为空,默认为:2.3.23
     * @return boolean  生成html是否成功,true为是,false为否
     */
    public static synchronized boolean createHtmlFileByFreemarker(Object dataModel, String ftlParentPath,
                                                                  boolean ftlParentPathIsAP, String ftlTemplateName,
                                                                  OutputStream outputStream, String encoding,
                                                                  String versionCode) throws GenericException {
        Version version = null;
        if (StringUtils.isBlank(encoding)) {
            encoding = DEFAULT_ENCODING;
        }
        if (StringUtils.isBlank(versionCode)) {
            //默认为2.3.23
            version = Configuration.VERSION_2_3_23;
        } else {
            version = new Version(versionCode);
        }
        if (dataModel == null) {
            LOGGER.error("[根据ftl生成html]数据为空");
            throw new GenericException(PARAM_ERROR_CODE, PARAM_ERROR_DESC);
        }
        if (StringUtils.isBlank(ftlTemplateName)) {
            LOGGER.error("[根据ftl生成html]ftl模版的名字(ftlTemplateName)存在空的参数");
            throw new GenericException(PARAM_ERROR_CODE, PARAM_ERROR_DESC);
        }
        //如果是绝对路径则ftl模版文件的父路径必填
        if (ftlParentPathIsAP && StringUtils.isBlank(ftlParentPath)) {
            LOGGER.error("[根据ftl生成html]ftl模版文件的父路径(ftlParentPath)不能为空");
            throw new GenericException(PARAM_ERROR_CODE, PARAM_ERROR_DESC);
        }

        //如果ftl模版名字不是以.ftl结尾的
        if (!ftlTemplateName.endsWith(".ftl")) {
            LOGGER.error("[根据ftl生成html] ftl模版的名字(ftlTemplateName)名称有误,不是.ftl后缀");
            throw new GenericException(PARAM_ERROR_CODE, PARAM_ERROR_DESC);
        }
        Writer out = null;
        try {
            Configuration configuration = getConfiguration(version, encoding, ftlParentPath, ftlParentPathIsAP);
            //以指定编码读取ftl文件
            Template template = configuration.getTemplate(ftlTemplateName, encoding);
            out = new BufferedWriter(new OutputStreamWriter(outputStream, encoding), 10240);
            template.process(dataModel, out);
            //LOGGER.info("[根据ftl生成html]生成html成功");
            return true;
        } catch (Exception e) {
            LOGGER.error("[根据ftl生成html]生成html出错", e);
            throw new GenericException(HTML_CREATE_ERROR_CODE, HTML_CREATE_ERROR_DESC);
        } finally {
            try {
                if (outputStream != null) {
                    outputStream.flush();
                    outputStream.close();
                }
                if (out != null) {
                    out.flush();
                    out.close();
                }
            } catch (Exception e) {
                LOGGER.error("", e);
                throw new GenericException(HTML_CREATE_ERROR_CODE, HTML_CREATE_ERROR_DESC);
            }
        }
    }

    /**
     * description: 根据html修改的ftl模版填入数据生成html的方法(如果模版是word,转成html编辑成ftl模版即可)
     * @param dataModel         数据模型
     * @param ftlParentPath     ftl文件的父路径,相对路径或者绝对路径,相对路径时指:相对classpath的路径,
     *                          可为空,当表示绝对父路径时必填,相对父路径时可不填,不填默认加载配置文件中的:
     *                          spring.freemarker.template-loader-path=classpath:/templates/ 的配置
     * @param ftlParentPathIsAP ftl文件的父路径是否是绝对路径,true--是,false-否
     * @param ftlTemplateName   ftl文件名称,需以.ftl结尾
     * @param encoding          编码,可为空,默认为:utf-8
     * @param versionCode       版本号,可为空,默认为:2.3.23
     * @return java.lang.String  直接返回生成的html字符串
     */
    public static synchronized String createHtmlFileByFreemarker(Object dataModel, String ftlParentPath,
                                                                 boolean ftlParentPathIsAP, String ftlTemplateName,
                                                                 String encoding, String versionCode) throws GenericException {
        Version version = null;
        if (StringUtils.isBlank(encoding)) {
            encoding = DEFAULT_ENCODING;
        }
        if (StringUtils.isBlank(versionCode)) {
            //默认为2.3.23
            version = Configuration.VERSION_2_3_23;
        } else {
            version = new Version(versionCode);
        }
        if (dataModel == null) {
            LOGGER.error("[根据ftl生成html]数据为空");
            throw new GenericException(PARAM_ERROR_CODE, PARAM_ERROR_DESC);
        }
        if (StringUtils.isBlank(ftlTemplateName)) {
            LOGGER.error("[根据ftl生成html]ftl模版的名字(ftlTemplateName)存在空的参数");
            throw new GenericException(PARAM_ERROR_CODE, PARAM_ERROR_DESC);
        }
        //如果是绝对路径则ftl模版文件的父路径必填
        if (ftlParentPathIsAP && StringUtils.isBlank(ftlParentPath)) {
            LOGGER.error("[根据ftl生成html]ftl模版文件的父路径(ftlParentPath)不能为空");
            throw new GenericException(PARAM_ERROR_CODE, PARAM_ERROR_DESC);
        }

        //如果ftl模版名字不是以.ftl结尾的
        if (!ftlTemplateName.endsWith(".ftl")) {
            LOGGER.error("[根据ftl生成html] ftl模版的名字(ftlTemplateName)名称有误,不是.ftl后缀");
            throw new GenericException(PARAM_ERROR_CODE, PARAM_ERROR_DESC);
        }
        Writer out = null;
        try {
            Configuration configuration = getConfiguration(version, encoding, ftlParentPath, ftlParentPathIsAP);
            configuration.setTemplateExceptionHandler(TemplateExceptionHandler.RETHROW_HANDLER);
            configuration.setLogTemplateExceptions(false);
            //以指定编码读取ftl文件
            Template template = configuration.getTemplate(ftlTemplateName, encoding);
            out = new StringWriter();
            template.process(dataModel, out);
            //LOGGER.info("[根据ftl生成html]生成html成功");
            out.flush();
            return out.toString();
        } catch (Exception e) {
            LOGGER.error("[根据ftl生成html]生成html出错", e);
            throw new GenericException(HTML_CREATE_ERROR_CODE, HTML_CREATE_ERROR_DESC);
        } finally {
            try {
                if (out != null) {
                    out.close();
                }
            } catch (Exception e) {
                LOGGER.error("", e);
                throw new GenericException(HTML_CREATE_ERROR_CODE, HTML_CREATE_ERROR_DESC);
            }
        }
    }

    /**
     * description: html转化成pdf的方法
     * @param pdfOutputStream pdf输出流
     * @param htmlInputStream html输入流
     * @param encoding        编码,可为空,默认为:UTF-8
     * @return void 无
     */
    public static synchronized void parseHtml2Pdf(OutputStream pdfOutputStream, InputStream htmlInputStream,
                                                  String encoding) throws GenericException {
        if (StringUtils.isBlank(encoding)) {
            encoding = DEFAULT_ENCODING;
        }
        //html的内容
        StringBuffer htmlContent = new StringBuffer();
        BufferedReader br = null;
        PdfWriter writer = null;
        try {
            br = new BufferedReader(new InputStreamReader(htmlInputStream, encoding));
            String line;
            while ((line = br.readLine()) != null) {
                htmlContent.append(line);
            }
            Document document = new Document();
            writer = PdfWriter.getInstance(document, pdfOutputStream);
            document.open();
            if ("linux".equals(getCurrentOperatingSystem())) {

                XMLWorkerHelper.getInstance().parseXHtml(writer, document,
                        new ByteArrayInputStream(htmlContent.toString().getBytes(encoding)), null,
                        Charset.forName(encoding), new ChinessFontProvider());
            } else {
                XMLWorkerHelper.getInstance().parseXHtml(writer, document,
                        new ByteArrayInputStream(htmlContent.toString().getBytes(encoding)),
                        Charset.forName(encoding));
            }
            document.close();

            //LOGGER.info("[html转pdf]html转pdf成功");
        } catch (Exception e) {
            LOGGER.error("[html转pdf]html转pdf出错", e);
            throw new GenericException(PARSE_HTML_TO_PDF_ERROR_CODE, PARSE_HTML_TO_PDF_ERROR_DESC);
        } finally {
            try {
                if (br != null) {
                    br.close();
                }
                if (htmlInputStream != null) {
                    htmlInputStream.close();
                }
                if (pdfOutputStream != null) {
                    pdfOutputStream.flush();
                    pdfOutputStream.close();
                }
                if (writer != null) {
                    writer.flush();
                    writer.close();
                }
            } catch (Exception e) {
                LOGGER.error("[html转pdf]html转pdf出错", e);
                throw new GenericException(PARSE_HTML_TO_PDF_ERROR_CODE, PARSE_HTML_TO_PDF_ERROR_DESC);
            }
        }
    }

    /**
     * description: html转化成pdf的方法
     * @param pdfOutputStream pdf输出流
     * @param htmlContent     html的内容
     * @param encoding        编码,可为空,默认为:UTF-8
     * @return void 无
     */
    public static synchronized void parseHtml2Pdf(OutputStream pdfOutputStream, String htmlContent,
                                                  String encoding) throws GenericException {
        if (StringUtils.isBlank(encoding)) {
            encoding = DEFAULT_ENCODING;
        }
        if (StringUtils.isBlank(htmlContent)) {
            LOGGER.error("[html转pdf]html内容为空");
            throw new GenericException(PARSE_HTML_TO_PDF_ERROR_CODE, PARSE_HTML_TO_PDF_ERROR_DESC);
        }
        //   //LOGGER.info("[html转pdf]html内容为:" + htmlContent);
        PdfWriter writer = null;
        try {
            Document document = new Document();
            writer = PdfWriter.getInstance(document, pdfOutputStream);
            document.open();
            if ("linux".equals(getCurrentOperatingSystem())) {

                XMLWorkerHelper.getInstance().parseXHtml(writer, document,
                        new ByteArrayInputStream(htmlContent.getBytes(encoding)), null,
                        Charset.forName(encoding), new ChinessFontProvider());
            } else {
                XMLWorkerHelper.getInstance().parseXHtml(writer, document,
                        new ByteArrayInputStream(htmlContent.getBytes(encoding)),
                        Charset.forName(encoding));
            }
            document.close();

            //LOGGER.info("[html转pdf]html转pdf成功");
        } catch (Exception e) {
            LOGGER.error("[html转pdf]html转pdf出错", e);
            throw new GenericException(PARSE_HTML_TO_PDF_ERROR_CODE, PARSE_HTML_TO_PDF_ERROR_DESC);
        } finally {
            try {
                if (pdfOutputStream != null) {
                    pdfOutputStream.flush();
                    pdfOutputStream.close();
                }
            } catch (Exception e) {
                LOGGER.error("[html转pdf]html转pdf出错", e);
                throw new GenericException(PARSE_HTML_TO_PDF_ERROR_CODE, PARSE_HTML_TO_PDF_ERROR_DESC);
            }
        }

    }

    /**
     * description: 获取当前的操作系统的方法
     * @param
     * @return java.lang.String 操作系统名称
     */
    private static synchronized String getCurrentOperatingSystem() {
        String os = System.getProperty("os.name").toLowerCase();
        //LOGGER.info("---------当前操作系统是-----------" + os);
        return os;
    }

    /**
     * description: 使用Freemarker使用html的ftl模版生成pdf的方法,ftl模版由html改名而来
     * 实现方式为通过freemaker根据ftl模版生成html文件,再将html转化为pdf,中间有临时文件html
     * @param dataModel             装入ftl模版的数据
     * @param htmlFtlParentPath     html修改的ftl文件父路径,相对路径或者绝对路径,相对路径时指:相对classpath的路径
     *                              可为空,当表示绝对父路径时必填,相对父路径时可不填,不填默认加载配置文件中的:
     *                              spring.freemarker.template-loader-path=classpath:/templates/ 的配置
     * @param htmlFtlParentPathIsAP ftl文件的父路径是否是绝对路径,true--是,false-否
     * @param htmlFtlTemplateName   ftl文件名称,需以.ftl结尾
     * @param htmlFileTempPath      临时html文件存放的位置,需绝对路径,且以.html结尾,可为空,为空时不经过html中间文件直接生成pdf
     * @param pdfOutputStream       生成的pdf输出流
     * @param encoding              编码,可为空,默认为:utf-8
     * @param versionCode           版本号,可为空,默认为:2.3.23
     * @date: 2020/11/15 21:39
     */
    public static synchronized void createPdfByFreemarker(Object dataModel, String htmlFtlParentPath,
                                                          boolean htmlFtlParentPathIsAP, String htmlFtlTemplateName,
                                                          String htmlFileTempPath, OutputStream pdfOutputStream,
                                                          String encoding, String versionCode) throws GenericException {
        //生成的临时html文件
        File tempHtmlFile = null;
        try {
            //如果html临时文件的路径为空则直接生成pdf文件
            if (StringUtils.isBlank(htmlFileTempPath)) {
                //=============== 直接生成pdf,不生成中间html节省服务器空间=============
                String htmlContent = PdfTool.createHtmlFileByFreemarker(dataModel, htmlFtlParentPath,
                        htmlFtlParentPathIsAP, htmlFtlTemplateName, encoding, versionCode);
                PdfTool.parseHtml2Pdf(pdfOutputStream, htmlContent, encoding);
            } else {
                //处理临时文件路径
                if (!htmlFileTempPath.toLowerCase().endsWith(".html")) {
                    LOGGER.error("[ftl生成pdf]html临时文件路径不是以.html结尾");
                    throw new GenericException(PARAM_ERROR_CODE, PARAM_ERROR_DESC);
                }
                //==============方便调试,生成html中间文件再生成pdf========================
                //获取html临时文件的文件夹,如果不存在则创建
                String htmlDirsPath = StringUtils.substringBeforeLast(htmlFileTempPath, "/");
                File htmlDirs = new File(htmlDirsPath);
                if (!htmlDirs.exists()) {
                    htmlDirs.mkdirs();
                }
                tempHtmlFile = new File(htmlFileTempPath);
                FileOutputStream htmlFileOutputStream = new FileOutputStream(tempHtmlFile);
                //先生成html临时文件
                boolean createHtmlSuccess = PdfTool.createHtmlFileByFreemarker(dataModel, htmlFtlParentPath,
                        htmlFtlParentPathIsAP, htmlFtlTemplateName, htmlFileOutputStream, encoding, versionCode);
                //如果html生成成功则读取html
                if (createHtmlSuccess) {
                    FileInputStream htmlFileInputStream = new FileInputStream(tempHtmlFile);
                    //再将html文件转化为pdf
                    PdfTool.parseHtml2Pdf(pdfOutputStream, htmlFileInputStream, encoding);
                    //LOGGER.info("[ftl生成pdf]生成pdf成功");
                } else {
                    LOGGER.error("[ftl生成pdf]生成pdf失败");
                    throw new GenericException(PDF_CREATE_ERROR_CODE, PDF_CREATE_ERROR_DESC);
                }
            }
        } catch (GenericException e) {
            throw e;
        } catch (Exception e) {
            LOGGER.error("[ftl生成pdf]生成pdf出错", e);
            throw new GenericException(PDF_CREATE_ERROR_CODE, PDF_CREATE_ERROR_DESC);
        } finally {
            //删除临时文件
            if (tempHtmlFile != null && tempHtmlFile.exists()) {
                //  tempHtmlFile.delete();
            }
        }
    }

    /**
     * description: 将word转化为pdf的方法,支持.doc和.docx格式的word,实现方式为先将word转化为html,再将html转化为pdf
     * @param wordInputStream  word输入流
     * @param pdfOutputStream  pdf输出流
     * @param docName          word名称,需带后缀
     * @param imageFolderPath  word中如果有图片的话,图片所在的文件夹路径,绝对路径
     * @param htmlFileTempPath html临时文件存储的路径,绝对路径,且以.html结尾
     * @param encoding         编码,可为空,默认为:utf-8
     * @return void 无
     */
    public static synchronized void word2Pdf(InputStream wordInputStream, OutputStream pdfOutputStream,
                                             String docName, String imageFolderPath, String htmlFileTempPath,
                                             String encoding) throws GenericException {
        if (StringUtils.isBlank(htmlFileTempPath)) {
            LOGGER.error("[word转pdf]html临时文件路径为空");
            throw new GenericException(PARAM_ERROR_CODE, PARAM_ERROR_DESC);
        }
        //处理临时文件路径
        if (StringUtils.isNotBlank(htmlFileTempPath) && !htmlFileTempPath.toLowerCase().endsWith(".html")) {
            LOGGER.error("[word转pdf]html临时文件路径不是以.html结尾");
            throw new GenericException(PARAM_ERROR_CODE, PARAM_ERROR_DESC);
        }
        if (StringUtils.isBlank(encoding)) {
            encoding = DEFAULT_ENCODING;
        }
        //生成的临时html文件
        File tempHtmlFile = null;
        FileOutputStream htmlOutputStream = null;
        try {
            //获取html临时文件的文件夹,如果不存在则创建
            String htmlDirsPath = StringUtils.substringBeforeLast(htmlFileTempPath, "/");
            File htmlDirs = new File(htmlDirsPath);
            if (!htmlDirs.exists()) {
                htmlDirs.mkdirs();
            }
            tempHtmlFile = new File(htmlFileTempPath);
            htmlOutputStream = new FileOutputStream(tempHtmlFile);
            //先将word转为html
            boolean htmlSuccess = WordTool.word2Html(wordInputStream, htmlOutputStream, docName, imageFolderPath);
            //如果生成html成功则读取html文件
            if (htmlSuccess) {
                //由于生成的html mate未闭合,手动对mate进行闭合做以下处理
                org.jsoup.nodes.Document document = Jsoup.parse(tempHtmlFile, encoding);
                //获取mate标签
                org.jsoup.select.Elements elements = document.getElementsByTag("META");
                if (elements != null) {
                    Iterator<org.jsoup.nodes.Element> it = elements.iterator();
                    while (it != null && it.hasNext()) {
                        //处理meta标签,进行闭合
                        it.next().appendText(" ");
                    }
                }
                //===============可以重新写入新的html,再读取,方便调试查看==========================
               /* htmlOutputStream = new FileOutputStream(tempHtmlFile);
                //重新写入html文件
                htmlOutputStream.write(document.html().getBytes(encoding));
                htmlOutputStream.flush();
                htmlOutputStream.close();
                htmlOutputStream = null;
                //再读取新的html文件
                FileInputStream htmlInputStream = new FileInputStream(tempHtmlFile);
                //再将生成的html转化为pdf
                PdfTool.parseHtml2Pdf(pdfOutputStream, htmlInputStream, encoding);*/

                //====================也可以直接使用jsoup处理后的html生成pdf===================
                //直接将html内容转化为pdf
                PdfTool.parseHtml2Pdf(pdfOutputStream, document.html(), encoding);

                //LOGGER.info("[word转pdf]word转pdf成功");
            } else {
                LOGGER.error("[word转pdf]word转pdf失败");
                throw new GenericException(PARSE_WORD_TO_PDF_ERROR_CODE, PARSE_WORD_TO_PDF_ERROR_DESC);
            }
        } catch (GenericException e) {
            throw e;
        } catch (Exception e) {
            LOGGER.error("[word转pdf]word转pdf出错", e);
            throw new GenericException(PARSE_WORD_TO_PDF_ERROR_CODE, PARSE_WORD_TO_PDF_ERROR_DESC);
        } finally {
            try {
                if (htmlOutputStream != null) {
                    htmlOutputStream.flush();
                    htmlOutputStream.close();
                }
            } catch (Exception e) {
            }
            //删除html临时文件
            if (tempHtmlFile != null && tempHtmlFile.exists()) {
                tempHtmlFile.delete();
            }
        }
    }

    /**
     * @packageName: com.emoon.utils
     * @className: ChinessFontProvider
     * @description: itext加载中文的类
     * @version: 1.0.0
     */
    static class ChinessFontProvider extends XMLWorkerFontProvider {
        private static final Logger LOGGER = LoggerFactory.getLogger(ChinessFontProvider.class);

        //重写获取字体的方法
        @Override
        public Font getFont(String fontname, String encoding, boolean embedded, float size, int style,
                            BaseColor color) {
            BaseFont bf = null;
            try {
                //加载resources文件夹下的font下的字体文件
                bf = BaseFont.createFont("font/simsun.ttf", BaseFont.IDENTITY_H, BaseFont.NOT_EMBEDDED);
            } catch (Exception e) {
                LOGGER.error("[加载中文]加载中文出错", e);
            }
            Font font = new Font(bf, size, style, color);
            font.setColor(color);
            return font;
        }
    }
}

   	@Value("${template.ftlTemplateName}")
    private String ftlTemplateName;
    
    @SneakyThrows
    @Override
    public void download(String id, HttpServletRequest request, HttpServletResponse response) {
        Map<String, Object> hyData = cgzbCghyMapper.getHyData(id);
        if (hyData == null || hyData.size() == 0) {
            throw new GenericException(purchaseCodeEnum.HY_IS_NULL.getCode(), purchaseCodeEnum.HY_IS_NULL.getMsg());
        }
        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm");
        SimpleDateFormat timeFormat = new SimpleDateFormat("HH:mm");
        String time = null;
        try {
            Date time1 = format.parse(hyData.get("time").toString());;
        } catch (ParseException e) {
            e.printStackTrace();
        }
        Map<String, Object> dataMap = new HashMap<>(16);
        dataMap.put("qdsj", time);
        dataMap.put("hydd", hyData.get("address"));
        dataMap.put("hynr", hyData.get("content"));
        dataMap.put("chry", hyData.get("chry"));
        dataMap.put("zcbm", hyData.get("hyzcbm"));
        String newPdfName = "会议签到单.pdf";
        OutputStream outputStream = null;
        //设置要下载的文件的名称
        String s;
        try {
            s = fileService.encodeChineseDownloadFileName(request, newPdfName);
            response.setHeader("Content-Disposition", "inline;fileName=" + s);
            //设置MIME类型
            response.setContentType("application/pdf;charset=UTF-8");
            outputStream = response.getOutputStream();
        } catch (Exception e) {
            e.printStackTrace();
        }
        PdfTool.createPdfByFreemarker(dataMap, null, false,
                this.ftlTemplateName, null, response.getOutputStream(), null,
                null);
    }
 /**
     * description:对文件流输出下载的中文文件名进行编码 屏蔽各种浏览器版本的差异性
     * @param request  http请求
     * @param fileName 文件名称
     * @return java.lang.String 新的zip名称
     */
    public String encodeChineseDownloadFileName(HttpServletRequest request, String fileName) throws Exception {

        String newFileName = null;
        String agent = request.getHeader("USER-AGENT");
        if (null != agent) {
            if (-1 != agent.indexOf("Firefox")) {//Firefox
                newFileName =
                        "=?UTF-8?B?" + (new String(org.apache.commons.codec.binary.Base64.encodeBase64(fileName.getBytes(
                                "UTF-8")))) + "?=";
            } else if (-1 != agent.indexOf("Chrome")) {//Chrome
                newFileName = new String(fileName.getBytes(), "ISO8859-1");
            } else {//IE7+
                newFileName = java.net.URLEncoder.encode(fileName, "UTF-8");
                newFileName = newFileName.replace("+", "%20");
            }
        } else {
            newFileName = fileName;
        }
        return newFileName;
    }
  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值