word转FreeMarker的ftl文件编辑导出编辑后的word

1.ftl文件介绍

ftl是Freemarker模板的文件后缀名
FreeMarker其实是一种比较简单的网页展示技术,说白了就是网页模板和数据模型的结合体。这种结合模式的好处就是,分离了网页界面设计人员和编程人员的工作,让他们各司其职。
FreeMarker大致的工作方式是,网页模板里面嵌入了数据模型中的数据、FreeMarker自定义流程控制语言、FreeMarker自定义的操作函数等等,在装载网页的时候,FreeMarker模板自动从数据模型中提取数据,并解释整个网页为我们熟知的HTML页面。
在B/S程式设计中,常常有美工和程序员二个角色,他们具有不同专业技能:美工专注于表现——创建页面、风格、布局、效果等等可视元素;而程序员则忙于创建程式的商业流程,生成设计页面要显示的数据等等。
模板引擎就是为了解决上面的问题而产生的。在设计HTML的时候,我们加入一些特定指令来指定要插入哪些数据,这些加了特殊指令的HTML或者其他文本,称为模板(Template)。而模板引擎会在输出页面时,用适当的数据替代这些代码,模板和嵌入JSP的HTML是不同的,模板指令只有很有限的编程能力,可以避免混入商业逻辑。

2.word编辑步骤

   2.1 word模板编辑

  •             word可以把要编辑的部分改为$对象.属性或$属性名转为xml文件,$符号与属性名称分开,去掉多余行,把$属性名称写一起
  •            word中含有图片需要模板中传入图片转为xml文件,图片转为文件流,把文件流中的图片替换为$对象.属性或$属性名。
  •            把xml文件改后缀,改为ftl文件。
  •            把ftl文件放在项目指定的路径下。

.doc转为xml文件

文字

 

图片

 

图片只要把binaryData中的字符流改为${变量名}就可以。

3.后台代码

   

package com.model.controller;



import freemarker.template.Configuration;
import freemarker.template.Template;

import org.apache.commons.lang3.RandomStringUtils;
import org.apache.log4j.Logger;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import sun.misc.BASE64Encoder;
import sun.net.www.protocol.http.HttpURLConnection;

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


/**
 * word 下载
 * Created by xxx on 2018/11/6.
 */
@Controller
@RequestMapping("/project")
public class ProjectController {

    private static Logger logger=Logger.getLogger(ProjectController.class);



    /**
     *  下载
     * @param response
     */
    @RequestMapping(value="/download")
    public void download(HttpServletResponse response){
        try{
            Map<String,Object> map=new HashMap<String,Object>(6);
            //组装返回数据
            completeData(map);
            //建立下载文件名称
            String fileName = Long.toString(System.currentTimeMillis()) + RandomStringUtils.randomNumeric(10) + ".doc";
            //修改文件模板
            File file=writeFileTemplate(fileName,map);
            //导出文件
            exportFile(response,file);
        }catch(Exception e){
            logger.error(" download file error",e);
        }
    }

    /**
     * 导出文件
     * @param response
     * @param file
     */
    public  void exportFile(HttpServletResponse response,File file){
        try{
            ServletOutputStream out=response.getOutputStream();
            BufferedInputStream in=new BufferedInputStream(new FileInputStream(file));
            response.setContentType("application/octet-stream;charset=UTF-8");
            response.setHeader("Content-Disposition", "attachment;filename=" + file.getName());
            byte[] buffer=new byte[1024];
            int count=0;
            while((count=in.read(buffer))!=-1){
                out.write(buffer,0,count);
            }
            out.flush();
            out.close();
        }catch(Exception e){
            logger.error("export word error",e);
        }finally{
            file.delete();
        }
    }

    /**
     * 修改文件模板
     * @param fileName
     * @param map
     * @return
     * @throws Exception
     */
    public File writeFileTemplate(String fileName,Map<String,Object> map) throws Exception{
        try{
            //设置freemarker模板编码、路径、模板名称
            Configuration configuration=new Configuration();
            configuration.setDefaultEncoding("utf-8");
            String tempPath=this.getClass().getResource("").getPath().substring(0,this.getClass().getResource("").getPath().indexOf("WEB-INF"));
            String templatePath=tempPath+"WEB-INF/exportTemplates/trademark/";
            configuration.setDirectoryForTemplateLoading(new File(templatePath));
            Template template=configuration.getTemplate("model.ftl");
            //设置输出文件路径
            String outPath=tempPath+"WEB-INF/tempFile/"+fileName;
            File outFile=new File(outPath);
            Writer writer=null;
            try{
               writer=new OutputStreamWriter(new FileOutputStream(outFile), "utf-8");
               template.process(map,writer);
            }catch(Exception e){
                logger.error("template write data error",e);
                throw e;
            }finally{
                writer.close();
            }
            return outFile;
        }catch(Exception e){
            logger.error("ProjectController.writeFileTemplate  error",e);
            throw e;
        }
    }

    /**
     * 组装返回数据
     * @param map
     * @return
     * @throws Exception
     */
    public Map<String,Object> completeData(Map<String,Object> map)throws Exception{
        try{
            map.put("name","张三");
            map.put("department","技术部");
            map.put("projectName","灿烂");
            map.put("year","2018");
            map.put("month","11");
            map.put("day","8");
            File file=saveToFile("http://mm.yh31.com:88/tp/sdj/201712241958292972.jpg");
            String imageBase64 = encodeBase64File(file);
            map.put("picture",imageBase64);
        }catch(Exception e){
            logger.error("ProjectController.completeData error",e);
            throw e;
        }
        return map;
    }

    /**
     * 通过url获取文件
     * @param destUrl
     */
    public File saveToFile(String destUrl) {
        FileOutputStream fos = null;
        BufferedInputStream bis = null;
        HttpURLConnection httpUrl = null;
        URL url = null;
        int BUFFER_SIZE = 1024;
        byte[] buf = new byte[BUFFER_SIZE];
        int size = 0;
        //在填写文件路径时,一定要写上具体的文件名称(xx.txt),否则会出现拒绝访问。
        File file = new File("E:\\download\\picture.png");
        if(!file.exists()){
            //先得到文件的上级目录,并创建上级目录,在创建文件
            file.getParentFile().mkdir();
            try {
                //创建文件
                file.createNewFile();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        try {
            url = new URL(destUrl);
            httpUrl = (HttpURLConnection) url.openConnection();
            httpUrl.connect();
            bis = new BufferedInputStream(httpUrl.getInputStream());
            fos = new FileOutputStream(file);
            while ((size = bis.read(buf)) != -1) {
                fos.write(buf, 0, size);
            }
            fos.flush();
        } catch (IOException e) {
        } catch (ClassCastException e) {
            logger.error("url transfer to http url error",e);
            throw e;
        } finally {
            try {
                fos.close();
                bis.close();
                httpUrl.disconnect();
            } catch (IOException e) {
            } catch (NullPointerException e) {
            }
        }

        return file;
    }

    /**
     * 将文件转化为Base64编码
     * @param file
     * @return
     * @throws Exception
     */
    public static String encodeBase64File(File file) throws Exception {
        //File file = new File(path);;
        FileInputStream inputFile = new FileInputStream(file);
        byte[] buffer = new byte[(int) file.length()];
        inputFile.read(buffer);
        inputFile.close();
        return new BASE64Encoder().encode(buffer);
    }

}

4.测试中遇到的问题

    4.1 方法public File saveToFile(String destUrl)中的 httpUrl = (HttpURLConnection) url.openConnection();因为HttpUrl与Url引用的java包不一致,Url是.net而HttpURL是apache,为此统一改为.net包

   4.2 获取文件路径的问题,详见博文https://blog.csdn.net/weixin_41926301/article/details/83818927

   4.3 方法public File writeFileTemplate(String fileName,Map<String,Object> map) throws Exception;其中

   writer=new OutputStreamWriter(new FileOutputStream(outFile), "utf-8")错误的写法
   writer=new OutputStreamWriter(new FileOutputStream(outFile))会造成文件输出的编码不是utf-8的格式,从而造成下载后的文件不可读。

5.运行结果

   

  • 2
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 可以使用Freemarker通过FTL模板导出带有表格的Word文档。在模板中,可以使用Freemarker的语法来定义表格的结构和内容。然后,使用Java代码将模板和数据合并,生成Word文档。在生成Word文档时,可以使用Apache POI或其他类库来操作Word文档的格式和内容。 ### 回答2: 在搭建Web应用程序时,我们通常会使用一些模板引擎来设计和生成页面。其中一个非常常见的模板引擎就是Freemarker,它的最大特点就是支持导出Word带有表格的操作。 首先,我们需要了解Freemarker是如何工作的。简单来说,Freemarker是一种基于模板的代码生成器,它将模板和数据结构组合起来,并生成具有特定文本格式的结果。在生成过程中,我们可以通过使用模板中的标签来定义输出的格式和样式,从而达到实现特定需求的目的。因此,如果我们想导出Word带有表格的文档,就需要在Freemarker模板中设置表格的格式和内容。 下面是一个示例代码片段,展示了如何使用Freemarker生成带有表格的Word文档: ``` <#import "jodconverter.ftl" as jodconverter> <#import "office.ftl" as office> <#assign tableData = [ ["Name", "Age", "Gender"], ["Tom", 25, "Male"], ["Lucy", 23, "Female"], ["Jack", 29, "Male"] ]> <#assign tableStyle = office.createTableStyle("tableStyle", { "border-width" : "1", "border-color" : "#000000", "background-color" : "#f0f0f0" })> <#assign tableModel = office.createTableModel("tableModel", { "data" : tableData, "columns" : [{ "width" : "100px" }, { "width" : "50px" }, { "width" : "50px" }] })> <#assign document = jodconverter.convert(inputStream, outputStream)> <#assign table = office.createTable("table", tableModel, tableStyle)> ${table} <#assign outputStream = document.getOutputStream()> ``` 在上述代码中,我们首先定义了一个表格数据和一个表格样式。然后,我们使用`office.createTableModel()`方法创建一个表格模型,并将表格数据和样式传入。接着,我们使用`office.createTable()`方法根据表格模型和样式创建实际的表格。最后,我们将表格输出到Word文档中。 需要注意的是,在上述代码中,我们使用了JODConverter来实现将Freemarker生成的文档换为Word格式的操作。这是因为Freemarker本身并不能直接生成Word文档,而是需要将生成的内容通过其他工具换为Word格式。JODConverter正是其中一种常用的工具,它可以将生成的文档换为多种格式,包括Word、Excel、PDF等。 综上所述,通过使用Freemarker模板引擎和JODConverter工具,我们可以实现将带有表格的文档导出Word格式的操作。这一过程需要仔细设置表格的格式和内容,以确保生成的文档符合预期的要求。 ### 回答3: FreeMarker是一种Java模板引擎,它通过模板文件生成输出文件。其中,ftlFreeMarker模板文件的扩展名。通过使用FreeMarker,我们可以在模板中定义标记和变量来生成各种格式的文本文件,如HTML、XML、JSON、CSV,甚至Word文档。而在这篇文章中,我将着重讲述如何使用FreeMarker生成带有表格的Word文档。 首先,我们需要引入FreeMarker的依赖。由于FreeMarker是一种Java模板引擎,因此我们需要在Java项目中添加FreeMarker的依赖。具体方法可以查看FreeMarker官方文档:http://freemarker.apache.org/docs/api/。 接下来,我们需要准备一个FTL模板文件。模板中可以包含Word文档中的各种元素,例如标题、段落、文本、图片等,并且可以用表达式调用Java程序定义的方法和变量。我们需要在模板中定义一个表格,并设置好表格的列数和行数,以及表格内容的格式和位置。 下面是一个简单的示例,用于生成一个带有两行两列的表格: ``` <#list tableData as tr> <#if tr_index == 0> <table> <tr> <th>ID</th> <th>Name</th> </tr> </#if> <tr> <td>${tr.id}</td> <td>${tr.name}</td> </tr> <#if tr_index == tableData?size-1> </table> </#if> </#list> ``` 在这个示例中,我们使用了`<#list>`标签来遍历数据集合(在本例中为`tableData`),并使用`<#if>`标签来判断是否需要添加表头和表尾。在表格中,我们用`${}`表达式来输出数据,其中`${tr.id}`和`${tr.name}`是Java数据模型中的属性或者方法。 最后,我们需要编写Java程序来将数据插入到FTL模板中,并导出Word文档。首先,我们需要创建一个Configuration对象,并指定模板文件的路径: ``` Configuration configuration = new Configuration(Configuration.VERSION_2_3_31); configuration.setDefaultEncoding("UTF-8"); configuration.setTemplateExceptionHandler(TemplateExceptionHandler.RETHROW_HANDLER); // 模板文件的路径 configuration.setDirectoryForTemplateLoading(new File("template")); // 加载模板文件 Template template = configuration.getTemplate("table.ftl"); ``` 然后,我们需要创建一个Map来存储需要导出Word文档的数据,并将Map传递给模板: ``` Map<String, Object> data = new HashMap<>(); data.put("tableData", tableData); // 将Map传递给模板 Writer writer = new FileWriter(new File("table.doc")); template.process(data, writer); ``` 在这个示例中,我们将数据存储在一个Map中,并以`tableData`为键名,将数据传递给模板。模板将使用`${tr.id}`和`${tr.name}`来获取数据,并将数据填充到相应的位置。最后,我们使用`template.process()`方法将Map传递给模板,并将要导出文件写入到文件中。 总之,通过FreeMarker模板引擎的强大功能,我们可以轻松地生成各种格式的文本文件,包括带有表格的Word文档。在实际应用中,我们可以根据需求编写不同样式的模板,并使用Java程序将数据填充到模板中,生成符合要求的文本文件
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值