动态Word生成以及文件下载、批量打包压缩下载



推荐内容

前言

分享一下Java实现动态Word的生成分享两种方法:FreeMarker 、poi-tl
以及对文件的下载以及批量打包下载


一、实现动态Word的生成

1.1、FreeMarker 是什么?

FreeMarker是一款模板引擎: 即一种基于模板和要改变的数据, 并用来生成输出文本(HTML网页、电子邮件、配置文件、源代码等)的通用工具。 它不是面向最终用户的,而是一个Java类库,是一款程序员可以嵌入他们所开发产品的组件。
FreeMarker是免费的,基于Apache许可证2.0版本发布。其模板编写为FreeMarker Template Language(FTL),属于简单、专用的语言。需要准备数据在真实编程语言中来显示,比如数据库查询和业务运算, 之后模板显示已经准备好的数据。在模板中,主要用于如何展现数据, 而在模板之外注意于要展示什么数据
在这里插入图片描述

1.2、使用步骤

1.2.1引入库

导入相应环境maven依赖

<dependency>
      <groupId>org.freemarker</groupId>
      <artifactId>freemarker</artifactId>
      <version>2.3.28</version>
    </dependency>

1.2.2.实际操作

FreeMarker使用的原理就是把Word模版转换为XML格式,再转换为FTL文件

Word测试文件 例:红色为动态替换区域
在这里插入图片描述
文件另存为XML格式
在这里插入图片描述
XML中找到替换区域进行替换 FreeMarker的格式为${},最好在word中固定完格式,然后保存完文件把后缀换为.ftl
在这里插入图片描述

在这里插入图片描述

然后可以创建一个工具类 用来生成动态Word
其中OutputStreamWriter流一定要设置编码“UTF-8”,要不然生成Word乱码

@Data
public class WordUtil {
    private  Configuration configuration = null;
    /*
     * 模板文件存放的目录
     */
    private String baseDir;
    /*
     * 模板文件名称
     */
    private String templateFile;
    /*
     * word生成的输出目录
     */
    private String outputDir;

    public WordUtil(){
        configuration = new Configuration(Configuration.VERSION_2_3_28);
        configuration.setDefaultEncoding("UTF-8");
    }
    /*
     * 转换成word
     */
    public File createWord(Map<String,Object> dataMap){
        configuration.setClassForTemplateLoading(this.getClass(), "");//模板文件所在路径
        Template t = null;
        try {
            //得到模板文件
            configuration.setDirectoryForTemplateLoading(new File(baseDir));
            t = configuration.getTemplate(templateFile);
        } catch (IOException e) {
            e.printStackTrace();
        }
        String createTime = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMddHHmmss"));
        File outFile = new File( outputDir+createTime+ "Test.doc"); //导出文件
        Writer out = null;
        try {
            out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(outFile),"UTF-8"));
        } catch (FileNotFoundException | UnsupportedEncodingException e1) {
            e1.printStackTrace();
        }
        try {
            t.process(dataMap, out); //将填充数据填入模板文件并输出到目标文件
        } catch (TemplateException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return outFile;
    }

@Test
    public void test2(){
            // 调用word文档帮助类
            WordUtil wordUtil = new WordUtil();
            // 模板文件存放的目录
            wordUtil.setBaseDir("D:\\javaProject\\untitled\\src\\main\\resources");
            // 模板文件名称
            wordUtil.setTemplateFile("test.ftl");
            // word生成的输出目录
            wordUtil.setOutputDir("D:\\javaProject\\untitled\\src\\main\\java\\");
            // 初始化数据map
            Map<String,Object> dataMap = new HashMap<>();
            // 录入采购基本数据
            dataMap.put("name","张三");
            dataMap.put("number","77777777");
            dataMap.put("money",9999999);

             wordUtil.createWord(dataMap);
    }

生成结果
在这里插入图片描述

1.3、poi-tl是什么?

poi-tl是一个基于Apache POI的Word模板引擎,也是一个免费开源的Java类库。同类型的FreeMarker或Velocity基于文本模板和数据生成新的html页面或配置文件。而poi tl是一个基于Word模板和数据生成新文档的Word模板引擎。

Word模板具有丰富的样式。Poi-tl将在生成的文档中完美地保留模板中的样式。也可以设置标记的样式。标记的样式将应用于替换的文本,因此您可以专注于模板设计。

poi-tl是一个“无逻辑”模板引擎。没有复杂的控制结构和变量分配,只有标签,有些标签可以用文本、图片、表格等代替,有些标签会隐藏某些文档内容,而另一些标签会循环一系列文档内容。

1.4、使用步骤

1.4.1、引入库

导入相应环境maven依赖

之前遇到项目poi版本冲突,需要查看项目引入合适版本

<dependency>
  <groupId>com.deepoove</groupId>
  <artifactId>poi-tl</artifactId>
  <version>1.12.2</version>
</dependency>

1.4.2、实际操作

poi-tl使用的原理是直接在docx文档进行替换

在这里插入图片描述

  @GetMapping("/exportWord")
  public void exportWord(HttpServletResponse response) throws FileNotFoundException {
      //存放数据,也就是填充在word里面的值
      Map<String, Object> params = new HashMap<>();
      params.put("title","动态Word");
      params.put("name","张三");
      params.put("text","测试使用poi-tl模版导出word");

      //模板路径
      // String templatePath = "E:\\demo\\word.docx";
      // 或模板在静态资源的相对路径
      File rootFile = new File((ResourceUtils.getURL("classpath:").getPath()));
      File templateFile = new File(rootFile, "/static/templates/exportWord.docx");
      //jar包获取不到文件路径`
      //URLDecoder.decode() 解决获取中文名称文件路径乱码
      String templatePath = URLDecoder.decode(templateFile.getPath());
      //生成文件名
      String fileName = new SimpleDateFormat("yyyyMMddHHmmss").format(new Date()) + "_" + System.currentTimeMillis();
      // 导出wold
      try {
          // 导出Word文档为文件
          XWPFTemplate template = XWPFTemplate.compile(templatePath).render(params);
          // 将导出的Word文件转换为流
          response.setContentType("application/octet-stream");
          response.setHeader("Content-disposition","attachment;filename=\""+fileName+".docx"+"\"");
          // HttpServletResponse response
          OutputStream out = response.getOutputStream();
          BufferedOutputStream bos = new BufferedOutputStream(out);
          template.write(bos);
          bos.flush();
          out.flush();
          // 最后不要忘记关闭这些流。
          PoitlIOUtils.closeQuietlyMulti(template, bos, out);
      } catch (Exception e) {
          System.out.println("导出Word文档时出现异常:" + e.getMessage());
      }
  }

二、实现Word的批量打包压缩下载

前端获取相应批量文件信息,然后再配置相应文件路径实现打包压缩下载

@ResponseBody
@RequestMapping(value ={"download"})
public String download( HttpServletRequest request, HttpServletResponse response, Model model) throws IOException{
    JSONObject jsonObject= new JSONObject();
    String file = request.getParameter("ids");
    //生成路径
    String path=zxSysParameterService.getParamValue("OutputDir");
    List<String> filePathList = new ArrayList<String>();
    response.setContentType("multipart/form-data");
    ZipOutputStream out = null;
    try{
        String createTime = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMddHHmmss"));
        String zipFileName=createTime+" JQZM.zip";
        String zipFilePath = path +zipFileName.
        response.setHeader(
                "content-disposition","attachment:filename="+zipFileName);
        out= new ZipOutputStream(response.getOutputStream());
        String[] files = file.split(",");
            for (String fileName :files){
                String path1="";
                path1= path + fileName;
                filePathList.add(path1);
            }
	// 普通压缩,下载文件信息
	zipFiles(filePathList,zipFilePath,out);
	//将文件写入本地,以便查看历史
	zipFiles(filePathList,zipFilePath,null);
	response.flushBuffer();
	}catch (Exception e){
	        CreditLogUtils.error(e.getMessage());
	        CreditLogUtils.error("本次下载有异常发生",e);
	    }finally {
	        if(null !=out){ try {
	            out.close();
	        }catch(IOException e){
	            e.printStackTrace();
	        }}
	    }
	    jsonObject.put("flag","下载文件成功");
	    return jsonObject.toJsONString();
}
private static void zipFiles(List<String> files,String zipFilePath,ZipOutputStream zouts) {
        File zipFile = new File(zipFilePath);
        try {
            if (zouts == null) {
                zouts = new ZipOutputStream(new FileOutputStream(zipFile));
            }
            for (int i = 0; i < files.size(); i++) {
                File txtFile = null;
                try {
                    txtFile = new File(files.get(i));
                    if (txtFile.isFile()) {
                        FileInputStream fin = null;
                        ZipEntry entry = null;
                        //创建复制缓冲区
                        byte[] buf = new byte[4096];
                        int readByte = 0;
                        //创建一个文件输入流
                        fin = new FileInputStream(txtFile);
                        //创建-个ZipEntry
                        entry = new ZipEntry(txtFile.getName());
                        //存储信息到压缩文件
                        zouts.putNextEntry(entry);
                        //复制字节到压缩文件
                        while ((readByte = fin.read(buf)) != -1) {
                            zouts.write(buf, 0, readByte);
                        }
                        zouts.closeEntry();
                        fin.close();
                    }
                } catch (FileNotFoundException e) {
                    CreditLogUtils.error("打包发生IO异常");
                }
            }
        } catch (IOException e) {
            CreditLogUtils.error("打包发生IO异常");
        } finally {
            if (zouts != null) {
                try {
                    zouts.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

点击阅读全文
Logo

一起探索未来云端世界的核心,云原生技术专区带您领略创新、高效和可扩展的云计算解决方案,引领您在数字化时代的成功之路。

更多推荐