freemarker构建word文档

freemarker优势:

很多时候我们构建的word文档都是有一定的格式标准,如果有多处地方都在生成同样格式的word文档,如果每一处都从头写,浪费时间,且大家的文档标准还不一定一样。完全可以事先创建好模板,然后直接往模板填值。

步骤:

1.本地创建word文档
 2.将动态处的数据写成${data}格式,类似jquery
 3.保存时选择文档格式为Word 2003 XML文档(*.xml)
 4.用编辑软件修改这个xml文档,因为在编译成xml时,可能会出现问题,正常格式是xx${data1}xx${data2}xx,结果编译后是     xx${data1}xx${??da???ta2}xx,手动把????这些错误的字符删掉,然后以UTF-8编码保存为ftl文件
 5.然后将ftl文件复制到项目,在freemarke构建项目时将会选择模板,填写值
 6.将ftl文件粘贴到com.yinhai.demo.ftl下
 7.查看代码
 8.图片特殊处理,事先的word文档插入一个死图片,在更改xml时,把这个死图片对应的死base64码换个一个${img}占位符,在代码里面把对应图片的base64码赋值进这个占位符就好了

/**
 * 通过freemarker构建word文档
 */
@RequestMapping("wordController!freemarkerToWord.do")
public String freemarkerToWord() throws Exception{
    HttpServletRequest req = getRequest();
    HttpServletResponse resp = getResponse();
    req.setCharacterEncoding("utf-8");
    Map<String, Object> map = new HashMap<String, Object>();
    Enumeration<String> paramNames = req.getParameterNames();
    // 通过循环将表单参数放入键值对映射中
    while(paramNames.hasMoreElements()) {
        String key = paramNames.nextElement();
        String value = req.getParameter(key);
        map.put(key, value);
    }

    // 把图片对应的base64放进map,准备赋值给word模板
    ServletContext servletContext = req.getServletContext();
    InputStream is = servletContext.getResourceAsStream("/img/freemarker/ta3.jpg");
    map.put("ta3_jpg", ImgToBase64Util.getImageString(is));

    // 提示:在调用工具类生成Word文档之前应当检查所有字段是否完整
    // 否则Freemarker的模板在处理时可能会因为找不到值而报错 这里暂时忽略这个步骤了
    File file = null;
    InputStream fin = null;
    ServletOutputStream out = null;
    try {
        // 调用工具类WordGenerator的createDoc方法生成Word文档
        file = WordGenerator.createDoc(map, "freemarker");
        fin = new FileInputStream(file);

        resp.setCharacterEncoding("utf-8");
        resp.setContentType("application/msword");
        // 设置浏览器以下载的方式处理该文件默认名为freemarker.doc
        resp.addHeader("Content-Disposition", "attachment;filename=freemarker.doc");

        out = resp.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();// 删除临时文件
        }
    }
    return JSON;
}

------------------------------------------------------------------------------------

工具类:

/**
 * 把Map里的值赋值进word模板,并返回File
 */
public class WordGenerator {

    private static Configuration configuration = null;
    private static Map<String, Template> allTemplates = null;

    static {
        configuration = new Configuration();
        configuration.setDefaultEncoding("utf-8");
        configuration.setClassForTemplateLoading(WordGenerator.class, "/com/yinhai/demo/ftl");
        allTemplates = new HashMap<String, Template>();
        try {
            //获取模板
            allTemplates.put("freemarker", configuration.getTemplate("freemarker.ftl"));
        } catch (IOException e) {
            e.printStackTrace();
            throw new RuntimeException(e);
        }
    }

    private WordGenerator() {
        throw new AssertionError();
    }

    public static File createDoc(Map<?, ?> dataMap, String type) {
        String name = "temp" + (int) (Math.random() * 100000) + ".doc";
        File f = new File(name);
        Template t = allTemplates.get(type);
        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;
    }

}

----------------------------------------------------------------------------------------------------------

/**
 * 图片的InputStream转成base64
 */
public class ImgToBase64Util {

    public static String getImageString(InputStream is) throws IOException {
        byte[] data = null;
        try {
            data = new byte[is.available()];
            is.read(data);
            is.close();
        } catch (IOException e) {
            throw e;
        } finally {
            if(is != null) {
                is.close();
            }
        }
        BASE64Encoder encoder = new BASE64Encoder();
        return data != null ? encoder.encode(data) : "";
    }

}

猜你喜欢

转载自blog.csdn.net/blossomfzq/article/details/82868239