文章目录

  • 准备 Freemarker 的 .ftl 模板文件
  • ① 先编写好 Word 模板
  • ② 编写实体类
  • ③ 将实体类中的属性填写到对应的位置。
  • ④ 另存为 XML 格式,并修改属性。修改完成后将文件尾缀修改为 .ftl
  • Freemarker 模板设置常见问题
  • 导出 word 带图片(比如加印章)
  • java代码实现下载
  • pom.xml
  • exportTaskNotice方法
  • exportWordUtil 方法
  • zipUtils 方法



准备 Freemarker 的 .ftl 模板文件
① 先编写好 Word 模板

freemarker ftl模板导出苹果笔记本打开空白 freemarker导出word_实体类

② 编写实体类

根据需要导出的 Word 模板编写对应的实体类。

public class TaskNotice{
    private Integer id;

    private Integer projectId;

    private String number;

    private String projectName;
	
	//省略.....
}
③ 将实体类中的属性填写到对应的位置。

比如:项目名称后面填写projectName。

freemarker ftl模板导出苹果笔记本打开空白 freemarker导出word_java_02

④ 另存为 XML 格式,并修改属性。修改完成后将文件尾缀修改为 .ftl

注意:另存为 Word XML 文档(.xml) 格式,不要存 Word 2003 XML 文档(.xml) 或其它格式的 XML。
接下来就是在 xml 中找到我们第二步填写的那些参数,并将那些参数用占位符 ${参数} 替换掉。
保存,修改文件名尾缀为ftl。

Freemarker 模板设置常见问题
  • 日期问题
    解决方法有很多,介绍一个常用的。
    将参数 ${endTime} 中的变量名后面添加 ?string('你指定的日期格式') ,例:${endTime?string('yyy-MM-dd')} Freemarker文档说明: 日期格式处理.
  • 空值问题
    解决方法一:
    将参数 ${user} 中的变量名后面添加一个 !和默认值。例: ${user!"匿名用户"} ,此时如果参数 user 传入为 null 时,将会显示 “匿名用户”。 解决方法二:
    使用 if 指令。例:<#if user??>${user}</#if> ,此时如果参数 user 传入为 null 时,将什么都不显示。 Freemarker文档说明: 处理不存在的变量.
导出 word 带图片(比如加印章)

       步骤如上,同样是先把印章插入到 word 预定位置,然后另存为 xml 文件,然后用占位符 ${参数} 替换掉 xml 中被编码成 base64 字符串的图片,保存,修改文件尾缀为 .ftl 即可。

freemarker ftl模板导出苹果笔记本打开空白 freemarker导出word_freemarker_03


freemarker ftl模板导出苹果笔记本打开空白 freemarker导出word_freemarker_04

至此,Freemarker模板文件准备完毕。


java代码实现下载
pom.xml
<!-- 引入freeMarker的依赖包. -->
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-freemarker</artifactId>
    </dependency>
exportTaskNotice方法
@RestController
@RequestMapping(value = "/export",produces = "application/json;charset=utf-8")
public class ExportController{
	
    @Autowired
    private TaskNoticeService taskNoticeService;
    
    @Autowired
    private ZipUtils zipUtils;
	
   // 导出任务通知单
   @PostMapping("/exportTaskNotice")
   public String exportTaskNotice(HttpServletResponse response, @RequestParam(value = "id")Integer[] id) {
       try {
           String ftlname = "taskNotice.ftl";
           String filenamePrefix = "福建省台湾县生产任务通知单";
           //HACK
           List<TaskNotice> list = new ArrayList<>();
           for (Integer taskNoticeId : id) {
               TaskNotice taskNotice;
               try {
                   taskNotice= taskNoticeService.select(taskNoticeId );
               } catch (Exception e) {
                   e.printStackTrace();
                   return "操作失败!";
               }
               if (taskNotice != null) {
                   list.add(taskNotice);
               }
           }
           if(list.size() < 1){
               return "操作失败!";
           }
           exportWordUtil(response, ftlname, filenamePrefix, list);
           return "操作成功!";
       } catch (Exception e) {
           e.printStackTrace();
           return "操作失败!";
       }
   }
}
exportWordUtil 方法
/**
     * 提取公共代码 简化代码
     * @param response response
     * @param ftlName ftlName
     * @param filenamePrefix 存储文件名前缀
     * @param list list——根据id查询出的表单数据实体类的集合
     * @param <T> 泛型
     * @throws Exception 异常
     */
    private <T> void exportWordUtil(HttpServletResponse response, String ftlName, String filenamePrefix, List<T> list) throws Exception{
        //Configuration 用于读取ftl文件
        Configuration configuration = new Configuration(new Version("2.3.0"));
        configuration.setDefaultEncoding("utf-8");
        //路径分隔符修改 TODO 这里使用类加载器获取 ftl 文件路径(根据自己实际的文件位置来获取)
        String path = StringUtils.replace(ExportController.class.getClassLoader().getResource("word-model"+File.separator+ftlName).getPath(),"%5c",File.separator);
        path = StringUtils.substring(path,1,path.length()-ftlName.length()-1);

        //得到临时文件存放路径
        String tempPath = path+File.separator+"temp";


        /**
        * 以下是三种指定ftl文件所在目录路径的方式
        * 指定ftl文件所在目录的路径,而不是ftl文件的路径
        */
        //指定路径的第一种方式(适合加载Jar包内的资源)
//        configuration.setClassForTemplateLoading(this.getClass(), basePackagePath);
//        configuration.setClassLoaderForTemplateLoading(classLoader, basePackagePath);

        //指定路径的第二种方式(适合加载文件路径)
        configuration.setDirectoryForTemplateLoading(new File(path));

        //指定路径的第三种方式(基于Servlet Context,指的是基于WebRoot下的template下的framemaker.ftl文件)
//        configuration.setServletContextForTemplateLoading(request.getSession().getServletContext(), "/word-model");


        //以utf-8的编码读取ftl文件
        Template template = configuration.getTemplate(ftlName);

        if(list.size()==1){//单个直接下载
            String saveName = null;
            //根据不同的实体类型去获取其存储名saveName TODO 根据实际情况修改下列关于saveName的代码
            if(list.get(0) instanceof TaskNotice){
                saveName = "《"+filenamePrefix+"》"+".doc";
            }
            //if(list.get(0) instanceof QualityTrackingCardVO){
            //    saveName = "《"+filenamePrefix+"-"+((QualityTrackingCardVO) list.get(0)).getName()+"》"+".doc";
            //}

            //输出文档路径及名称
            ServletOutputStream outputStream = null;
            BufferedWriter bufferedWriter = null;
            try {
                //设置输出流
                response.reset();
                response.setContentType("application/msword");
                response.setCharacterEncoding("utf-8");
                response.addHeader("Content-Disposition" ,"attachment;filename=" + URLEncoder.encode(saveName,"utf-8"));
                outputStream = response.getOutputStream();
                bufferedWriter = new BufferedWriter(new OutputStreamWriter(outputStream,"UTF-8"));
                template.process(list.get(0), bufferedWriter);
            } finally {
                if(bufferedWriter!=null){
                    bufferedWriter.flush();
                    bufferedWriter.close();
                }
                if(outputStream!=null){
                    outputStream.flush();
                    outputStream.close();
                }
            }
        }else if(list.size() > 1) {//多个压缩后返回zip文件
            //创建临时资源文件夹 和 zip文件全路径
            String tempFolderPath = tempPath + File.separator + "temp-word-folder";
            String tempZipFilePath = tempPath + File.separator + filenamePrefix + "Batch.zip";
            File file = new File(tempFolderPath);
            if(!file.exists()){//创建临时文件夹
                file.mkdirs();
            }
            //批量生成word
            for (Object entity : list) {
                String saveName = null;
                //TODO 这里的saveName可能会重复,到时候问清楚
                //根据不同的实体类型去获取其存储名 saveName  TODO 根据实际情况修改下列获取 saveName 的代码
                if(entity instanceof TaskNotice){
                    saveName = "《"+filenamePrefix+"-"+((TaskNotice) entity).getId()+"》"+".doc";
                }
                //if(entity instanceof QualityTrackingCardVO){
                //    saveName = "《"+filenamePrefix+"-"+((QualityTrackingCardVO) entity).getName()+"》"+".doc";
                //}

                FileOutputStream fileOutputStream = null;
                BufferedWriter bufferedWriter = null;
                try {
                    fileOutputStream = new FileOutputStream(tempFolderPath + File.separator + saveName);
                    bufferedWriter = new BufferedWriter(new OutputStreamWriter(fileOutputStream,"UTF-8"));
                    template.process(entity, bufferedWriter);
                }finally {
                    if(bufferedWriter != null){
                        bufferedWriter.close();
                    }
                    if(fileOutputStream != null){
                        fileOutputStream.close();
                    }
                }
            }
            //打包成zip
            zipUtils.createZip(tempFolderPath,tempZipFilePath);
            //返回输出流
            ServletOutputStream outputStream = null;
            FileInputStream fileInputStream = null;
            try {
                fileInputStream = new FileInputStream(tempZipFilePath);
                //设置输出流
                response.reset();
                response.setContentType("application/x-download");
                response.setCharacterEncoding("utf-8");
                response.addHeader("Content-Disposition" ,"attachment;filename=" + URLEncoder.encode(filenamePrefix + "Batch.zip","utf-8"));
                outputStream = response.getOutputStream();
                byte[] buffer = new byte[1024];
                int len = 0;
                while ((len = fileInputStream.read(buffer)) != -1) {
                    outputStream.write(buffer,0,len);
                }
            } finally {//关闭流
                if(outputStream != null){
                    outputStream.flush();
                    outputStream.close();
                }
                if(fileInputStream != null){
                    fileInputStream.close();
                }
                zipUtils.deleteFile(new File(tempPath));//删除临时文件夹
            }
        }
    }
zipUtils 方法

链接: ZipUtils