栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

JAVA实现Freemarker生成动态数据的Word文档下载到浏览器

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

JAVA实现Freemarker生成动态数据的Word文档下载到浏览器

使用的jar包版本:freemarker-2.3.28.jar
使用开发工具:idea

1. 创建模板:

新建一个word文档,打开后编辑成想要的格式

动态数据替换成${xxx},如果是多条集合用${xx.xxx};
如果没有对应数据会报错。可以替换成${(xx.xxx)!''}  (这里表示改内容为空显示'')就不会报错了

优化后:

然后在word里面点击另存为 ——xml格式文件

然后把这个xml文件后缀改成.ftl 得到:

然后把文件拖到idea编译器里格式化一下代码格式

拉到下面大概看到一堆这样的代码 先不管

2.创建WordUtil工具类

WordUtil.java代码:

import java.io.*;
import java.net.URLEncoder;
import java.util.Map;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.gsgy.utils.DateUtil;
import freemarker.template.Configuration;
import freemarker.template.Template;
import org.springframework.util.ResourceUtils;

public class WordUtil {
    private static Configuration configuration = null;
    //模板文件的位置
    private static String templateFolder ="";

    static {
        try {
            //这个是获取到项目里的路径(对应resources文件夹下的template目录)
            templateFolder = ResourceUtils.getURL("classpath:").getPath()+ "template/";
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }
    }
    //或者注释上面的 选择这个固定的地址
    //    private static final String templateFolder = "D:/wzy/template";
    static {
        configuration = new Configuration();
        configuration.setDefaultEncoding("utf-8");
        try {
            configuration.setDirectoryForTemplateLoading(new File(templateFolder));
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    private WordUtil() {
        throw new AssertionError();
    }

    public static void exportMillCertificateWord(HttpServletRequest request, HttpServletResponse response, Map map, String title, String ftlFile) throws IOException {
        Template freemarkerTemplate = configuration.getTemplate(ftlFile);
        File file = null;
        InputStream fin = null;
        ServletOutputStream out = null;
        try {
            // 调用工具类的createDoc方法生成Word文档
            file = createDoc(map,freemarkerTemplate);
            fin = new FileInputStream(file);

            response.setCharacterEncoding("utf-8");
            response.setContentType("application/msword");
            // 设置浏览器以下载的方式,处理该文件名
            String fileName = title+ DateUtil.getDateTimeByTimestamp() + ".doc";
            response.setHeader("Content-Disposition", "attachment;filename="
                    .concat(String.valueOf(URLEncoder.encode(fileName, "UTF-8"))));

            out = response.getOutputStream();
            byte[] buffer = new byte[512];
            int bytesToRead = -1;
            // 通过循环将读入的Word文件的内容输出到浏览器中
            while((bytesToRead = fin.read(buffer)) != -1) {
                out.write(buffer, 0, bytesToRead);
            }

        } finally {
            if(fin != null) fin.close();
            if(out != null) out.close();    //关闭对应流
            if(file != null) file.delete(); // 删除临时文件
        }
    }

    private static File createDoc(Map dataMap, Template template) {
        String name =  "sellPlan.doc";
        File f = new File(name);
        Template t = template;
        try {
            // 这个地方不能使用FileWriter因为需要指定编码类型否则生成的Word文档会因为有无法识别的编码而无法打开
            Writer w = new OutputStreamWriter(new FileOutputStream(f), "utf-8");
            t.process(dataMap, w);
            w.close();
        } catch (Exception ex) {
            ex.printStackTrace();
            throw new RuntimeException(ex);
        }
        return f;
    }
}

这里注意:(设置文件名)
String fileName = title+ DateUtil.getDateTimeByTimestamp() + “.doc”;
DateUtil.getDateTimeByTimestamp() 是我这边获取当前时间的接口 复制过去会报错 自己替换一下

建一个Controller类写调用接口:

@RestController
@RequestMapping("test")
public class testController{

 	@Autowired
    private YwXsRyxxService ywXsRyxxService;


	@RequestMapping("/getWord")
    @ResponseBody
    public void getWord(HttpServletResponse response) {

        //---------------这里开始调用自己需要的数据(粘过去替换成自己的数据方法)--------------------
        Page page = new Page();
        //人员
        List ryList = ywXsRyxxService.selectlistPage(page);
		//-----------------------------结束------------------------------------------


        //封装数据
        Map map = new HashMap();
        map.put("ryList", ryList);
        try {
        //这里设置文档的名称 和模板的名字
            WordUtils.exportMillCertificateWord(getRequest(), response, map, "文档名称", "ypbg.ftl");
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
}
3.回到模板哪里

这里我们封装了ryList 和wlList两个集合


在模板里CTRL+F 搜索 人员信息

然后慢慢往下 会看到 姓名 、性别 ~~~ 等名称(不熟悉这个文档的小白可以大致看一眼结构)

继续往下看到第一个动态数据姓名的替换符哪里(下图1处)

然后看上图2处 的

<#list ryList as ry> 这里的ryList 是我们后台封装过来的数据
ry是别名  
就是模板里定义的变量名ry.xxxx

找到<#list ryList as ry> 下面 这个标签的结尾处 如图:

后面加上

以下二选一
(1)然后将模板放在项目的 resources/template目录下 (没有就建一个)
(2)本地找个文件夹下新建一个template文件夹 把路径考到代码里下面图片位置把2处的值替换了。然后注释1处代码


项目下路径图

4.启动项目

启动项目 在浏览器输入对应的请求路径
我这是: http://localhost:8088/test/getWord
然后浏览器会下载一个word


一个简单的文档就生成了,复杂的继续摸索延伸。希望能帮到大家 (代码部分有参考网上的文章,自己学习整理了下)

最后加一些Freemarker中用到的判断的语法供参考:
${(xxx)!''}  //判断xxx为null 输出''
<#list ryList as ry>  //循环遍历集合
<#if xxx?? >  //判断xxx变量是否存在,存在执行里面内容;同java里if判断
<#if type??> 
	<#if type == 1>是
	<#if type == 0>否

${(dateTime?string('yyyy-MM-dd HH:mm:ss'))!''}  //实体类Date类型会报错 这样转换一下(替换dateTime为自己的变量名)
转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/337686.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号