zoukankan      html  css  js  c++  java
  • FreeMarker生成带图片的word文档(浏览器输出)

    所需依赖

    <!--生成word文档所需-->
    <dependency>
    <groupId>org.freemarker</groupId>
    <artifactId>freemarker</artifactId>
    <version>2.3.28</version>
    </dependency>

    <dependency>
    <groupId>dom4j</groupId>
    <artifactId>dom4j</artifactId>
    <version>1.6.1</version>
    </dependency>

    制作模板的步骤参见上篇博客,有一点需要注意的是document.xml中图片路径保存成本地路径格式以支持各种图片格式写入至文档。

     这里的路径搞了好长时间,简单记录一下:

     这里的文件名要使用这种格式才能在xml文件中保存为全路径名称,不知道是不是我wps的问题,最后是使用了这种方法完成的。

    下面记录一下使用的主要代码:

    FreeMarker工具类:
    public class FreeMarkerUtil {
    
    
        public static Configuration getConfiguration() throws IOException{
            //创建配置实例
            Configuration configuration = new Configuration(Configuration.VERSION_2_3_28);
            //设置编码
            configuration.setDefaultEncoding("utf-8");
            //设置模板加载文件夹(模板路径)
            String pathName = ConstantFactory.me().getFilePath()+"templates"+File.separator;
            configuration.setDirectoryForTemplateLoading(new File(pathName));
            return configuration;
        }
    
    
        /**
         * 获取模板字符串
         * @param dataMap   参数
         * @param templateName  模板名称
         * @return
         */
        public static String getFreemarkerContent(Map dataMap, String templateName) {
            String result = "";
            try {
                Configuration configuration = getConfiguration();
                //获取模板
                Template template = configuration.getTemplate(templateName,"utf-8");
    
                StringWriter swriter = new StringWriter();
                //生成文件
                template.process(dataMap, swriter);
                result = swriter.toString();
    
    
            } catch (Exception e) {
                e.printStackTrace();
            }
            return result;
        }
    
    
        /**
         * 获取模板字符串输入流
         * @param dataMap   参数
         * @param templateName  模板名称
         * @return
         */
        public static ByteArrayInputStream getFreemarkerContentInputStream(Map dataMap, String templateName) {
            ByteArrayInputStream in = null;
    
            try {
                Configuration configuration = getConfiguration();
                //获取模板
                Template template = configuration.getTemplate(templateName,"utf-8");
    
                StringWriter swriter = new StringWriter();
                //生成文件
                template.process(dataMap, swriter);
                in = new ByteArrayInputStream(swriter.toString().getBytes("utf-8"));
    
            } catch (Exception e) {
                e.printStackTrace();
            }
            return in;
        }
    
    }

    word工具类:

    生成本地文件时更改outputStream 输出流形式即可

    public class WordUtil {
    
        private final static String separator = File.separator;
        private final static String xmlDocument = "document.xml";
        private final static String xmlDocumentXmlRels = "document.xml.rels";
        private final static String xmlContentTypes = "[Content_Types].xml";
    
        /**
         * 生成评价数据word文档
         * @param outputStream 浏览器输出流
         * @param dataMap 填充数据
         * @param templateDocxPathName docx模板全路径名称
         * @return
         * @author xWang
         * @Date 2020-06-17
         */
        public void createDocx(OutputStream outputStream,Map dataMap, String templateDocxPathName) {
    
            try {
    
                //获取 document.xml 输入流
                ByteArrayInputStream documentInput = FreeMarkerUtil.getFreemarkerContentInputStream(dataMap, xmlDocument);
    
                //获取 document.xml.rels 输入流
                String xmlDocumentXmlRelsComment = FreeMarkerUtil.getFreemarkerContent(dataMap, xmlDocumentXmlRels);
    
                ByteArrayInputStream documentXmlRelsInput =
                        new ByteArrayInputStream(xmlDocumentXmlRelsComment.getBytes("utf-8"));
    
                //获取 header1.xml 输入流
                //ByteArrayInputStream headerInput = FreeMarkUtils.getFreemarkerContentInputStream(dataMap, xmlHeader, templatePath);
    
                //获取 [Content_Types].xml 输入流
                ByteArrayInputStream contentTypesInput = FreeMarkerUtil.getFreemarkerContentInputStream(dataMap, xmlContentTypes);
    
                //读取 document.xml.rels  文件 并获取rId 与 图片的关系 (如果没有图片 此文件不用编辑直接读取就行了)
                Document document = DocumentHelper.parseText(xmlDocumentXmlRelsComment);
                Element rootElt = document.getRootElement(); // 获取根节点
                Iterator iter = rootElt.elementIterator();// 获取根节点下的子节点head
    
                List<Map> titleList = JSON.parseArray(JSON.toJSONString(dataMap.get("titleList")), Map.class);
                for (Map<String,Object> map:titleList
                ) {
                    List<Map> list = JSON.parseArray(JSON.toJSONString(map.get("optionsList")), Map.class);
    
                    // 遍历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) {
                            for (Map<String, String> picMap : list) {
                                if (target.endsWith(picMap.get("name"))) {
                                    picMap.put("rId", id);
                                }
                            }
                        }
                    }
                }
    
                File docxFile = new File(templateDocxPathName);
                if (!docxFile.exists()) {
                    docxFile.createNewFile();
                }
    
                ZipFile zipFile = new ZipFile(docxFile);
                Enumeration<? extends ZipEntry> zipEntrys = zipFile.entries();
                ZipOutputStream zipout = new ZipOutputStream(outputStream);
    
                //覆盖文档
                int len = -1;
                byte[] buffer = new byte[1024];
                while (zipEntrys.hasMoreElements()) {
                    ZipEntry next = zipEntrys.nextElement();
                    InputStream is = zipFile.getInputStream(next);
                    if (next.toString().indexOf("media") < 0) {
                        // 把输入流的文件传到输出流中
                        zipout.putNextEntry(new ZipEntry(next.getName()));
                        //写入图片配置类型
                        if (next.getName().equals("[Content_Types].xml")) {
                            if (contentTypesInput != null) {
                                while ((len = contentTypesInput.read(buffer)) != -1) {
                                    zipout.write(buffer, 0, len);
                                }
                                contentTypesInput.close();
                            }
    
                        } else if (next.getName().indexOf("document.xml.rels") > 0) {
                            //写入主数据配置信息
                            if (documentXmlRelsInput != null) {
                                while ((len = documentXmlRelsInput.read(buffer)) != -1) {
                                    zipout.write(buffer, 0, len);
                                }
                                documentXmlRelsInput.close();
                            }
                        } else if ("word/document.xml".equals(next.getName())) {
                            //写入主数据信息
                            if (documentInput != null) {
                                while ((len = documentInput.read(buffer)) != -1) {
                                    zipout.write(buffer, 0, len);
                                }
                                documentInput.close();
                            }
    
                        } else if ("word/header1.xml".equals(next.getName())) {
                            //写入页眉信息
    //                        if (headerInput != null) {
    //                            while ((len = headerInput.read(buffer)) != -1) {
    //                                zipout.write(buffer, 0, len);
    //                            }
    //                            headerInput.close();
    //                        }
                        } else {
                            while ((len = is.read(buffer)) != -1) {
                                zipout.write(buffer, 0, len);
                            }
                            is.close();
                        }
                    }
                }
    
                //写入新图片
                for (Map<String,Object> map:titleList
                ) {
                    List<Map> picList = JSON.parseArray(JSON.toJSONString(map.get("optionsList")), Map.class);
                    len = -1;
                    if (picList != null && !picList.isEmpty()) {
                        for (Map<String, String> pic : picList) {
                            ZipEntry next = new ZipEntry("word" + separator + "media" + separator + pic.get("name"));
                            zipout.putNextEntry(new ZipEntry(next.toString()));
                            InputStream in = new FileInputStream(pic.get("path"));
                            while ((len = in.read(buffer)) != -1) {
                                zipout.write(buffer, 0, len);
                            }
                            in.close();
                        }
                    }
                }
                zipout.close();
            } catch (Exception e) {
    //            System.err.println(e.getMessage());
                e.getStackTrace();
            }
        }
  • 相关阅读:
    paip.数据库全文检索 attilax总结
    软件网站安全性的设计与检测与解决方案
    防止SQL注入解决方案
    paip.账务系统的安全性
    快速开发字段很多的MIS表
    paip.php调试不能显示局部变量内容w/ xdebug
    程序安全性之配置文件安全
    paip.VS2010未能加载类型
    paip.盘古汉字转拼音组件库使用总结
    paip.跟踪DISCUZ积分日志功能总结
  • 原文地址:https://www.cnblogs.com/xiaowangxiao/p/13158757.html
Copyright © 2011-2022 走看看