Java 用Freemarker完美导出word文档(带图片)

标签: freemarker 输出word
32人阅读 评论(0) 收藏 举报
分类:

准备材料

1.word原件 2.编辑器(推荐Firstobject free XML editor)

实现步骤

1.用Microsoft Office Word打开word原件;

2.把需要动态修改的内容替换成***,如果有图片,尽量选择较小的图片几十K左右,并调整好位置;

3.另存为,选择保存类型Word 2003 XML 文档(*.xml)【这里说一下为什么用Microsoft Office Word打开且要保存为Word 2003XML,本人亲测,用WPS找不到Word 2003XML选项,如果保存为Word XML,会有兼容问题,避免出现导出的word文档不能用Word 2003打开的问题】;

4.用Firstobject free XML editor打开文件,选择Tools下的Indent【或者按快捷键F8】格式化文件内容。左边是文档结构,右边是文档内容;

5. 将文档内容中需要动态修改内容的地方,换成freemarker的标识。其实就是Map<String, Object>中key,如${landName};

6.在加入了图片占位的地方,会看到一片base64编码后的代码,把base64替换成${image},也就是Map<String, Object>中key,值必须要处理成base64;

  代码如:<w:binData w:name="wordml://自定义.png" xml:space="preserve">${image}</w:binData>

  注意:“>${image}<”这尖括号中间不能加任何其他的诸如空格,tab,换行等符号。

  如果需要循环,则使用:<#list maps as map></#list>  maps是Map<String, Object>中key,值为数组,map为自定义;

7. 标识替换完之后,模板就弄完了,另存为.ftl后缀文件即可。注意:一定不要用word打开ftl模板文件,否则xml内容会发生变化,导致前面的工作白做了。

代码实现

工具类WordUtils.Java

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStreamWriter;
import java.io.Writer;
import java.net.URLEncoder;
import java.util.Date;
import java.util.Map;

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

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

public class WordUtils {
     //配置信息,代码本身写的还是很可读的,就不过多注解了  
    private static Configuration configuration = null;  
    //这里注意的是利用WordUtils的类加载器动态获得模板文件的位置  
   // private static final String templateFolder = WordUtils.class.getClassLoader().getResource("../../").getPath() + "WEB-INF/templetes/";  
    private static final String templateFolder = "H:/我的项目/lm/lm/web/src/main/webapp/WEB-INF/templates";  
    static {  
        configuration = new Configuration();  
        configuration.setDefaultEncoding("utf-8");  
        try {  
            configuration.setDirectoryForTemplateLoading(new File(templateFolder));  
        } catch (IOException e) {  
            e.printStackTrace();  
        }  
   }  
  
    private WordUtils() {  
        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.formatDateDetailTime(new Date()) + ".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;  
    }  
}

Action

@RequestMapping("/exportSellPlan")
    public @ResponseBody void exportSellPlan(Long id){
        Calendar calendar = Calendar.getInstance();// 取当前日期。
        if(id!=null){
            SellPlan plan=sellService.getSellPlanInfo(id);
             //获得数据  
            Map<String, Object> map = new HashMap<String, Object>(); 
            map.put("bYear", plan.getBusinessYear()!=null?plan.getBusinessYear():"");
            map.put("lYear", plan.getLiveYear()!=null?plan.getLiveYear():"");
            map.put("leader",plan.getLeader()!=null?plan.getLeader():""); 
            map.put("phone", plan.getPhone()!=null?plan.getPhone():"");
            map.put("curYear", calendar.get(Calendar.YEAR)+"");
            map.put("image", getImageBase(plan.getPositionImage()));
            try {
                WordUtils.exportMillCertificateWord(getRequest(),getResponse(),map,"方案","sellPlan.ftl");
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }    
        }
    }

Base64处理

//获得图片的base64码
    @SuppressWarnings("deprecation")
    public String getImageBase(String src) {
        if(src==null||src==""){
            return "";
        }
        File file = new File(getRequest().getRealPath("/")+src.replace(getRequest().getContextPath(), ""));
        if(!file.exists()) {
            return "";
        }
        InputStream in = null;
        byte[] data = null;  
        try {
            in = new FileInputStream(file);
        } catch (FileNotFoundException e1) {
            e1.printStackTrace();
        }
        try {  
            data = new byte[in.available()];  
            in.read(data);  
            in.close();  
        } catch (IOException e) {  
          e.printStackTrace();  
        } 
        BASE64Encoder encoder = new BASE64Encoder();
        return encoder.encode(data);
    }

javascript

window.location.href="<%=path%>/exportSellPlan?id=" + id;

pom.xml

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

结束语

如果对Freemarker标签不熟的,可以在网上先学习下,了解文档结构。

相关链接

Firstobject free XML editor下载地址:http://www.firstobject.com/dn_editor.htm

freemarker 官网:http://freemarker.org/

 

原文转自:https://www.cnblogs.com/zwqh/p/7182953.html




查看评论

java中使用freemarker导出word文档

公司项目要求要有一个能导出成一份word文档的功能,于是就上网搜了一些教程,但我跟着教程使用的时候还是遇到了很多问题,这里我自己总结一份我作为新手使用freemarker能看懂的文章。可能以后自己还会...
  • IRainReally
  • IRainReally
  • 2017-09-21 15:17:48
  • 161

JAVA Freemarker 导出word文档实例带有图片

本实例是使用freemarker 将数据导出word文档,其他的也可以实现 实现导出word文档的步骤如下: 1.用户提供样例word文件 2.分析样例word文件,制作word模板文件(xml...
  • you_are_my_life
  • you_are_my_life
  • 2017-03-08 15:13:38
  • 5259

利用freemarker生成word(带图片)

freemarker是利用模板动态生成数据的形式的一种模板引擎,以下陈述纯属个人学习过程中的见解至于基本概念就不在此介绍(可以自行百度):         个人认为在以下情况比较适合利用freema...
  • ZHUCEYE
  • ZHUCEYE
  • 2015-10-29 11:14:19
  • 3991

Java用freemarker导出word例子

  • 2014年05月20日 11:26
  • 881KB
  • 下载

freemarker导出word文档对图片拉伸或拉长的处理

最近因为java项目中有大量的图片需要导出到word(采用freemarker导出模板),导出的过程中发现一个问题:导出饼图的时候会随着浏览器的大小不同被拉长或者拉伸,查阅很多质料但网上并没有找到相关...
  • xiaoxuexu
  • xiaoxuexu
  • 2017-12-01 10:37:51
  • 254

JAVA利用FreeMarker生成(导出)Word文档(Bug修改)

Bug一:把代码放到服务器上,能下载Word文件;但是,下载到服务器的C盘上了;  解决:  修改部分export.js代码:  function table01(){ var stime =...
  • u013456370
  • u013456370
  • 2017-05-08 10:52:55
  • 384

JAVA利用FreeMarker生成(导出)Word文档

一、首先下载相对应的jar包:freemarker.jar; 而我的项目环境是:maven 在pom.xml中: freemarker freemarker 2.3.8 二、自定义...
  • u013456370
  • u013456370
  • 2017-05-03 17:46:34
  • 1124

freemarker导出Word文档并在其中插入图片

先将word转成xml格式,再用notepad将其转为ftl格式(将要填入数据的地方加个占位符,${name})...
  • lixiyuyu
  • lixiyuyu
  • 2017-09-13 16:32:57
  • 929

java freemarker导出word -包含多张图片导出

  • 2016年11月23日 16:45
  • 915KB
  • 下载

java使用freemarker模板导出word(带有合并单元格)文档

前言:最近要做一个导出word功能,其实网上有很多的例子,但是我需要的是合并单元格的,可是查了好久都没有自己想要的。研究了几天其实挺简单的,在这儿我就简单的介绍一下吧!(此方法只是一种思路,借鉴者还有...
  • qq_33195578
  • qq_33195578
  • 2017-06-27 13:32:09
  • 2671
    个人资料
    等级:
    访问量: 535
    积分: 13
    排名: 228万+
    文章存档