SpringBoot以freemarker为word的模板下载文件到用户端(2)

这一篇和上一篇word模板下载到本地有一些区别,这里是下载到用户端的浏览器,其实是返回二进制给浏览器
如果你想看word怎么转成ftl模板的请看springboot使用freemarker模板生成word文档
这篇博客参考的ssm实现文件下载

一、工具类WordUntil



import com.alibaba.fastjson.JSON;
import freemarker.template.Configuration;
import freemarker.template.Template;
import lombok.extern.slf4j.Slf4j;

import java.io.*;
import java.nio.charset.StandardCharsets;
import java.util.Map;

/**
 * @author lenovo
 */
@Slf4j
public class WordUtil {

    /**
     * 生成word文件并返回二进制
     *
     * @param dataMap      word中需要展示的动态数据,用map集合来保存
     * @param templateName word模板名称,例如:model.ftl
     * @param fileName     生成的文件名称,例如:Test.doc
     */
    public static byte[] createWordByte(Map<String, Object> dataMap, String templateName, String fileName) throws IOException {
        File outFile = null;
        Writer out = null;
        try {
            //创建配置实例
            Configuration configuration = new Configuration(Configuration.VERSION_2_3_23);
            //设置编码
            configuration.setDefaultEncoding("utf-8");
            //ftl模板文件
            configuration.setClassForTemplateLoading(WordUtil.class, "/templates/down");
            //获取模板
            Template template = configuration.getTemplate(templateName);
            //输出文件
            outFile = new File(File.separator + fileName);
            //将模板和数据模型合并生成文件
            out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(outFile), StandardCharsets.UTF_8));
            //生成文件
            template.process(dataMap, out);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            //关闭流
            assert out != null;
            out.flush();
            out.close();
        }
        return getWordByte(outFile);
    }

    /**
     * 根据文件生成二进制数组
     *
     * @param outFile
     * @return
     */
    private static byte[] getWordByte(File outFile) {
        byte[] wordByte = null;
        try {
            FileInputStream fis = new FileInputStream(outFile);
            ByteArrayOutputStream bos = new ByteArrayOutputStream(1000);
            byte[] b = new byte[1000];
            int n;
            while ((n = fis.read(b)) != -1) {
                bos.write(b, 0, n);
            }
            fis.close();
            bos.close();
            wordByte = bos.toByteArray();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return wordByte;
    }

    /**
     * 生成word文件到本地
     *
     * @param dataMap      word中需要展示的动态数据,用map集合来保存
     * @param templatePath word模板的路径
     * @param templateName word模板名称,例如:model.ftl
     * @param filePath     文件生成的目标路径,例如:D:\\freemarker
     * @param fileName     生成的文件名称,例如:Test.doc
     */
    public static void createWordToLocal(Map<String, Object> dataMap, String templatePath, String templateName, String filePath, String fileName) throws IOException {
        File outFile = null;
        Writer out = null;
        try {
            //创建配置实例
            Configuration configuration = new Configuration(Configuration.VERSION_2_3_23);
            //设置编码
            configuration.setDefaultEncoding("utf-8");
            //ftl模板文件
            configuration.setClassForTemplateLoading(WordUtil.class, templatePath);
            //获取模板
            Template template = configuration.getTemplate(templateName);
            //输出文件
            outFile = new File(filePath + File.separator + fileName);
            //如果输出目标文件夹不存在,则创建
            if (!outFile.getParentFile().exists()) {
                if (!outFile.getParentFile().mkdirs()) {
                    log.error("创建文件到本地失败 dataMap:{}", JSON.toJSONString(dataMap));
                }
            }
            //将模板和数据模型合并生成文件
            out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(outFile), StandardCharsets.UTF_8));
            //生成文件
            template.process(dataMap, out);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            assert out != null;
            out.flush();
            out.close();
        }
    }

}

这里有两个静态方法入口

  1. 一个是返回word模板的二进制数组,由controller层返回这个二进制,
  2. 一个是保存word模板到本地,

这里主要是看看返回二进制数组的,
保存本地的请往SpringBoot以freemarker为word的模板下载文件到本地(1)

二、Controller层的写法

  @RequestMapping(value = "/downPurchaseOrder.do")
    @ResponseBody
    public ResponseEntity<byte[]> downPurchaseOrder(Long id) {
        Map<String, Object> dataMap = new HashMap<String, Object>(2);
        byte[] fileByte = null;
        try {
        	//可以认为dataMap和model扮演的角色一样
            dataMap.put("num", 1);
            fileByte = WordUtil.createWordByte(dataMap, "model.ftl", "测试单.doc");
            HttpHeaders headers = new HttpHeaders();
            headers.setContentDispositionFormData("attachment", URLEncoder.encode("测试.doc", "utf-8"));
            return new ResponseEntity<byte[]>(fileByte, headers, HttpStatus.CREATED);
        } catch (Exception e) {
            log.error("导出测试单失败 id:{}", id, e);
        }
        return null;
    }

三、前端的写法

 <a href="/down.do?id=1"  title="导出">下载word</a>

这样就完成了下载到用户端的操作

四、下载的文件的起名

如果你想让下载的文件的名称是后端定的,你就可以按上面的来
如果你想让下载的文件的名称是前端定的,你就可以按下面的来

 HttpHeaders headers = new HttpHeaders();
 headers.setContentDispositionFormData("attachment", URLEncoder.encode("测试单.doc", "utf-8"));
 return new ResponseEntity<byte[]>(fileByte, headers, HttpStatus.CREATED);

换成

 return new ResponseEntity<byte[]>(fileByte, HttpStatus.CREATED);

前端换成这样

<a href="/down.do?id=1"  title="导出" download="测试单.doc">下载word</a>

你可能感兴趣的:(springboot)