freemarker实现word导出功能

1.为什么选择freeMarker

1.导出的word模板固定,只是数据改变
2.快速简单

2.freeMarker是什么

FreeMarker是一个用Java语言编写的模板引擎,它基于模板来生成文本输出。FreeMarker与Web容器无关,即在Web运行时,它并不知道Servlet或HTTP。它不仅可以用作表现层的实现技术,而且还可以用于生成XML,JSP或Java 等。

目前企业中:主要用Freemarker做静态页面或是页面展示

3.怎么使用freemarker

  • 引入jar,这里用的是org.freemarker.freemarker下
//引入freemarker
    compile group: 'org.freemarker', name: 'freemarker', version: '2.3.28'
  • 模板生成和创建的工具类
package com.xxxx.xxxxx.util;

import freemarker.template.Configuration;
import freemarker.template.Template;
import freemarker.template.TemplateException;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.IOUtils;
import org.springframework.core.io.ClassPathResource;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.net.URLEncoder;
import java.util.Map;

/**
 * word 文档生成和下载工具类
 */
public class WordExprotUtils {
    /**
     * 浏览器下载 word文档
     * @param dataMap  用map集合来保存,word中需要加载展示的动态数据
     * @param templateName word模板名称,例如:complainTemplate.ftl
     * @param filePath 文件生成word文件的目标路径,例如:C:\Users\WangChong\Desktop(我们的桌面路径)
     * @param fileName 文件生成word文件名称
     * @param fileSuffixName 文件生成word文件名称的后缀名
     */
    public static void downLoadWord(Map<?,?> dataMap,String templateName,String filePath,String fileName,String fileSuffixName,HttpServletResponse response){
        File file = null;
        InputStream fin = null;
        ServletOutputStream out = null;
        try {
            //生产word文件
            file = createaWord(dataMap,filePath,fileName,fileSuffixName,templateName);
            //浏览器下载方式(下载的文件名可以自定命名,这里使用上一步word文件名)
            fin = new FileInputStream(file);
            response.setCharacterEncoding("utf-8");
            response.setContentType("application/msword");
            response.setHeader("Content-Disposition", "attachment;filename=".concat(String.valueOf(URLEncoder.encode(fileName+fileSuffixName, "UTF-8"))));
            out = response.getOutputStream();
            byte[] buffer = new byte[1024];  // 读写缓冲区
            int bytesToRead = -1;
            while((bytesToRead = fin.read(buffer)) != -1) {
                out.write(buffer, 0, bytesToRead);// 通过循环将读入的Word文件的内容输出到浏览器中
            }
        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            try {
                if(fin != null) {
                    fin.close();// 关闭文件输入流
                }
                if(out != null) {
                    out.close();// 关闭文件输出流
                }
                if(file != null) {
                    file.delete(); // 删除临时文件
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    /**
     *创建word文档
     * @param dataMap 用map集合来保存,word中需要加载展示的动态数据
     * @param filePath 生成word文件的目标路径,例如:C:\Users\WangChong\Desktop(我们的桌面路径)
     * @param fileName  生成word文件名称 例如:建议详情
     * @param fileSuffixName 生成word文件名称的后缀名 例如:.doc 或 .docx
     * @param templateName   word模板名称,例如:complainTemplate.ftl
     * @return file 返回创建的文件
     */
    private static File createaWord(Map<?, ?> dataMap,String filePath,String fileName,String fileSuffixName,String templateName) {
        Template freemarkerTemplate = null;
        File file = null;
        FileOutputStream fileOutputStream = null;
        Writer writer = null;
        File templateFile = null; //模板文件
        try {
            //1.配置类配置
            Configuration  configuration = new Configuration(Configuration.VERSION_2_3_28);//初始化配置 需要指定配置的版本
            configuration.setDefaultEncoding("utf-8");//设置默认的编码方式为utf-8
            //---------------------------------解决jar获取不到资源路径文件[开始]--------------------------------
            //解决思路:将模板放置在磁盘上读取
            // 首先获取类路径下的模板文件将其转化为输入流的方式
            // 然后在使用的计算上创建一个空的模板文件,这个文件可以是作为临时文件(即创建完使用后删除),也可以作为电脑磁盘上的永久文件。这里使用永久文件,防止频繁创建删除消耗磁盘寿命。
            // 再然后 将 上面的输入流复制到创建的模板文件。
            ClassPathResource classPathResource = new ClassPathResource("/templates/freeMarkerTemplate/"+templateName);
            InputStream inputStream = classPathResource.getInputStream();//先转输入流
            String templateDir = filePath+"/freeMarkerTemplate";//模板文件目录
            File dir = new File(filePath+"/freeMarkerTemplate");//目录不存在则创建
            if (!dir.exists()){
                dir.mkdirs();
            }
            templateFile = new File(templateDir+File.separator+templateName);//生成模板文件
            templateFile.createNewFile();//当且仅当不存在具有此抽象路径名指定名称的文件时,不可分地创建一个新的空文件。
            FileUtils.copyInputStreamToFile(inputStream, templateFile);//将流复制到目标文件后并关闭流
            IOUtils.closeQuietly(inputStream);//手动关闭
            //---------------------------------解决jar获取不到资源路径文件[结束]--------------------------------
            //2.设置模板
            configuration.setDirectoryForTemplateLoading(dir);//注意这里放的是模板文件的目录,而不是具体到模板文件
            //3.获取模板
            freemarkerTemplate  = configuration.getTemplate(templateName);
            //4.生成Word文档
            file = new File(templateDir+File.separator+fileName+fileSuffixName);//生成的word文档绝对路径
            fileOutputStream = new FileOutputStream(file);
            writer = new OutputStreamWriter(fileOutputStream, "utf-8");// 这个地方不能使用FileWriter因为需要指定编码类型否则生成的Word文档会因为有无法识别的编码而无法打开
            freemarkerTemplate.process(dataMap, writer);//生成word文档
        } catch (TemplateException e) {
            e.printStackTrace();
        }catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                if(fileOutputStream != null){
                    fileOutputStream.close();//关闭文件输出流
                }
                if(writer != null){
                    writer.close();//关闭写入流
                }
//                if(null != somethingFile){
//                    somethingFile.delete();//删除模板文件,这里不删除
//                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

        return file;
    }




}


  • 制作模板----.ftl文件
1.打开word ,绘制好模板样式,并在要动态展示的地方输入对应的变量名称。例如:${name}

在这里插入图片描述

2.另存为‘xml文件(*.xml)’文件

3.用编译器打开上一步的文件,检查变量是否都对(即和原来给的形式一样:例如${name} 符号之间没有多余的字符,如果有要将其删除)
在这里插入图片描述
4.重命名为以.ftl为后缀的文件。

在这里插入图片描述

参考文章:
https://www.jianshu.com/p/20fd71b2e6a0

发布了18 篇原创文章 · 获赞 2 · 访问量 650

猜你喜欢

转载自blog.csdn.net/qq_34699995/article/details/100726280