java freemarker 动态生成word,再转pdf

1.制作模板为动态导出做准备
因为转pdf需要docx格式。所有先弄一个word模板。
在这里插入图片描述
保存后再复制一个将后缀名改为zip压缩包的格式。解压取出document.xml和document.xml.rels。
document.xml对图片的设置
在这里插入图片描述
document.xml.rels设置动态图片地址
在这里插入图片描述
这样模板就配好了。
2.maven配置

	<!-- 如果只是想实现word导出,只需要这一个包:freemarker就行了 -->
    <dependency>
        <groupId>org.freemarker</groupId>
        <artifactId>freemarker</artifactId>
        <version>2.3.28</version>
    </dependency>
    <!-- 导出pdf需要使用的包:xdocreport -->
    <dependency>
        <groupId>fr.opensagres.xdocreport</groupId>
        <artifactId>org.apache.poi.xwpf.converter.core</artifactId>
        <version>1.0.4</version>
    </dependency>
    <dependency>
        <groupId>fr.opensagres.xdocreport</groupId>
        <artifactId>org.apache.poi.xwpf.converter.pdf</artifactId>
        <version>1.0.4</version>
    </dependency>
    <dependency>
        <groupId>fr.opensagres.xdocreport</groupId>
        <artifactId>fr.opensagres.xdocreport.itext.extension</artifactId>
        <version>1.0.4</version>
    </dependency>

3.生成word

 /**
 * @param dataMap               参数数据
 * @param docxTemplate          docx模主板名称
 * @param xmltemplateName       xml主模板名称
 * @param xmltConfigemplateName xml配置主模板名称 一般用来配置图片、样式信息
 * @param temp_path             模板存放路径
 * @param base_path             模板实际路径
 * @param output_path           产出路径
 * @param output_file_name      产出文件名称
 */
public static void createDocx(Map dataMap, String docxTemplate, String xmltemplateName, String xmltConfigemplateName, String temp_path, String base_path, String output_path, String output_file_name) {
    try {

        try {
            //================================拼装生成xml配置文档================================

            String xml_config_output_path = output_path + System.currentTimeMillis() + ".xml.rels";
            createTemplateXml(dataMap, xmltConfigemplateName, temp_path, xml_config_output_path);
            File xmlConfigFile = new File(xml_config_output_path);

            //读取 xmlConfigFile  文件 并获取rId 与 图片的关系
            String xmlConfigFile_content = getFreemarkerContent(dataMap, xmltConfigemplateName, temp_path);
            System.out.println("===========================xmlConfigFile_content================================");
            System.out.println(xmlConfigFile_content);
            System.out.println("===========================xmlConfigFile_content================================");
            Document document = DocumentHelper.parseText(xmlConfigFile_content);

            Element rootElt = document.getRootElement(); // 获取根节点
            Iterator iter = rootElt.elementIterator();// 获取根节点下的子节点head
            List<String> warn_list = new ArrayList<>();
            // 遍历Relationships节点
            while (iter.hasNext()) {
                Element recordEle = (Element) iter.next();
                String id = recordEle.attribute("Id").getData().toString();
                String target = recordEle.attribute("Target").getData().toString();
                if (target.indexOf("media") == 0) {
//                        System.out.println("id>>>"+id+"   >>>"+target);
//                        id>>>rId18   >>>media/pic1
                        warn_list.add(id);
                }
            }
            dataMap.put("warn_list", warn_list);
//                dataMap.put("","");
            //================================拼装生成xml配置文档================================


            //================================拼装生成主模板xml文档================================
            String xml_output_path = output_path + System.currentTimeMillis() + ".xml";
            createTemplateXml(dataMap, xmltemplateName, temp_path, xml_output_path);
            File xmlFile = new File(xml_output_path);
            //================================拼装生成主模板xml文档================================


            File docxFile = new File(base_path + docxTemplate);
            if (!docxFile.exists()) {
                docxFile.createNewFile();
            }


            ZipFile zipFile = new ZipFile(docxFile);
            Enumeration<? extends ZipEntry> zipEntrys = zipFile.entries();
            ZipOutputStream zipout = new ZipOutputStream(new FileOutputStream(output_path + output_file_name));


            int len = -1;
            byte[] buffer = new byte[1024];
            //------------------追加新图片------------------
//                List<String> picList = new ArrayList<>();
            Map<String, String> picFiles = (Map<String, String>) dataMap.get("pics");
            if (picFiles != null && !picFiles.isEmpty()) {
                for (String fileName : picFiles.keySet()) {
                    ZipEntry next = new ZipEntry("word" + File.separator + "media" + File.separator + fileName);
                    zipout.putNextEntry(new ZipEntry(next.toString()));
                    InputStream in = new FileInputStream(picFiles.get(fileName));
                    while ((len = in.read(buffer)) != -1) {
                        zipout.write(buffer, 0, len);
                    }
                    in.close();
                }
            }

            //------------------追加新图片------------------
            len = -1;
            while (zipEntrys.hasMoreElements()) {
                ZipEntry next = zipEntrys.nextElement();
                InputStream is = zipFile.getInputStream(next);
                // 把输入流的文件传到输出流中 如果是word/document.xml由我们输入
                zipout.putNextEntry(new ZipEntry(next.toString()));
                System.out.println(">>>>>>>>>" + next.isDirectory());
                System.out.println(">>>>>>>>>>>>>>>>>" + next.toString());
                System.out.println(">>>>>>>>>>>>>>>>>" + next.isDirectory());
                if ("word/document.xml".equals(next.toString())) {
                    InputStream in = new FileInputStream(xmlFile);
                    while ((len = in.read(buffer)) != -1) {
                        zipout.write(buffer, 0, len);
                    }
                    in.close();
                } else if (next.toString().indexOf("document.xml.rels") > 0) {
                    InputStream in = new FileInputStream(xmlConfigFile);
                    while ((len = in.read(buffer)) != -1) {
                        zipout.write(buffer, 0, len);
                    }
                    in.close();
                } else {
                    while ((len = is.read(buffer)) != -1) {
                        zipout.write(buffer, 0, len);
                    }
                    is.close();
                }
            }
            zipout.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    } catch (Exception e) {
        e.printStackTrace();
    }
}

/**
 * 生成主数据模板xml
 *
 * @param dataMap      数据参数
 * @param templateName 模板名称
 * @param pathPrefix   模板路径
 * @param filePath     生成路径
 */
public static void createTemplateXml(Map dataMap, String templateName, String pathPrefix, String filePath) {
    try {
        //创建配置实例
        Configuration configuration = new Configuration();

        //设置编码
        configuration.setDefaultEncoding("UTF-8");

        //ftl模板文件统一放至 com.lun.template 包下面
        configuration.setDirectoryForTemplateLoading(new File(path + "template/"));
//            configuration.setClassForTemplateLoading(FreemarkerWordUtils.class,"/template/doc");
        //configuration.setClassForTemplateLoading(WordToPDFUtil.class, pathPrefix);
        //获取模板
        Template template = configuration.getTemplate(templateName);

        //输出文件
        File outFile = new File(filePath);

        //如果输出目标文件夹不存在,则创建
        if (!outFile.getParentFile().exists()) {
            outFile.getParentFile().mkdirs();
        }

        //将模板和数据模型合并生成文件
        Writer out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(outFile), "UTF-8"));


        //生成文件
        template.process(dataMap, out);

        //关闭流
        out.flush();
        out.close();
    } catch (Exception e) {
        e.printStackTrace();
    }
}


public static String getFreemarkerContent(Map dataMap, String templateName, String temp_path) {
    String ret_str = "";
    try {
        //创建配置实例
        Configuration configuration = new Configuration();

        //设置编码
        configuration.setDefaultEncoding("UTF-8");

        //ftl模板文件统一放至 com.lun.template 包下面
        configuration.setDirectoryForTemplateLoading(new File(path + "template/"));
        //configuration.setClassForTemplateLoading(WordToPDFUtil.class, temp_path);
        //获取模板
        Template template = configuration.getTemplate(templateName);

        //输出文件
        //File outFile = new File(filePath);

        //如果输出目标文件夹不存在,则创建
//            if (!outFile.getParentFile().exists()){
//                outFile.getParentFile().mkdirs();
//            }

        //将模板和数据模型合并生成文件
//            Writer out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(outFile),"UTF-8"));

        StringWriter swriter = new StringWriter();
        //生成文件
        template.process(dataMap, swriter);
        ret_str = swriter.toString();


    } catch (Exception e) {
        e.printStackTrace();
    }
    return ret_str;
}

4.word 转pdf

/**
 * word转pdf
 * @param wordPath word的路径
 * @param pdfPath pdf的路径
 */
public static boolean wordToPdf(String wordPath, String pdfPath){
    logger.info("wordPath:{}, pdfPath:{}", wordPath, pdfPath);
    boolean result = false;
    try {
        logger.info("开始word转pdf");
        XWPFDocument document=new XWPFDocument(new FileInputStream(new File(wordPath)));
        File outFile=new File(pdfPath);
        outFile.getParentFile().mkdirs();
        OutputStream out=new FileOutputStream(outFile);
        PdfOptions options= PdfOptions.create();
        PdfConverter.getInstance().convert(document,out,options);
        logger.info("word转pdf成功");
        result = true;
    }
    catch (  Exception e) {
        e.printStackTrace();
        logger.error("word转pdf失败");
    }
    return result;
}

5.测试

public static String details = "珍琴是一名孤儿,八岁时被人领养并读华兴小学,11岁时,她读三年级,便遇到了小熙老师,小熙老师是她的代课老师,教英语。她是初中毕业然后读三年中专,毕完业后在华兴当三年级的代课老师。\n" +
        "                \n" +
        "                  她年轻开朗,活泼可爱。由于珍琴的英语老师怀孕了,所以课都是有小熙老师来上的,珍琴很有学英语的天赋,所以她成功的当上了小熙老师的课代表,珍琴很乖,很懂事,她上课也很认真,下课也不吵不闹,她工作认真负责。作业按时交齐,经常抽查背诵……小熙老师很喜欢她,她也很喜欢小熙老师。\n" +
        "                \n" +
        "                  但是那段时间,珍琴的养父母生了个儿子,根本没有时间,也没有精力去照顾珍琴,她一个人要扫地,拖地……干很多活,所以她总是在学校写完作业才回家。那是夏末初秋,一般她回家时都是太阳落山了,有一天她回家的路上,遇见了小熙老师,小熙老师问她怎么这么晚才回家,珍琴沉迷了许久才说嗯,我把作业都写完了……小熙老师对她笑了笑说,“上来吧,我送你回家。”说完,小熙老师指着她后面的后排座,珍琴有些犹豫,小熙老师摸了摸她的头说,“没事的,刚好顺路。来。\n" +
        "                \n" +
        "                  珍琴点点头,然后上去了,从此放学的每一天都是小熙老师送她回家的,直到有一天,小熙老师找到珍琴说,“对不起,今天我可能没有办法送你回家了,以后可能也没有办法了,不好意思。”珍琴摆摆手说没事,随后递给了她一个棒棒糖,小熙老师望着那根棒棒糖,然后问她,你喜欢吃棒棒糖啊?珍琴点点头,小熙老师摸了摸她的头,然后说谢谢。";
public static final String path = "D:/下载文件/git/mybatis/src/main/resources/";

public static final String xmltemplateName = "document.xml";//xml主模板名称
public static final String xmltConfigemplateName = "document.xml.rels";//xml配置主模板名称 一般用来配置图片、样式信息

public static void main(String[] args) {
    Map<String, Object> dataMap = new HashMap<>();
    dataMap.put("Edition", "v_1.0");
    SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
    dataMap.put("date", sdf.format(new Date()));
    //用户图片
    List<String> picList = new ArrayList<>();
    Map<String, String> pics = new HashMap<>();
    picList.add("summary_9.png");
    pics.put("summary_9.png", "D:\\迅雷下载\\summary_9.png");
    picList.add("summary_4.png");
    pics.put("summary_4.png", "D:\\迅雷下载\\summary_4.png");
    picList.add("summary_3.png");
    pics.put("summary_3.png", "D:\\迅雷下载\\summary_3.png");
    picList.add("summary_2.png");
    pics.put("summary_2.png", "D:\\迅雷下载\\summary_2.png");
    dataMap.put("picList", picList);
    dataMap.put("pics", pics);
    dataMap.put("details", details);
    String output_path = path + "static/";
    String output_file_name = "test.docx";
    String base_path = path + "template/";
    createDocx(dataMap, "test.docx", "document.xml",
            "document.xml.rels", path + "template/",
            base_path, output_path, output_file_name);
    WordAndPdfUtil.wordToPdf(output_path + "test.docx", output_path + "test.pdf");
}

6效果
word
在这里插入图片描述
pdf

在这里插入图片描述
在这里插入图片描述

评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值