zoukankan      html  css  js  c++  java
  • 导出到word

    导出到excel功能会常做,但是导出到word功能很少做,项目遇到,在这里做一下标记。

    导出到excel比较容易,excel都有固定格式也模板,但是word需要自己写模板,这里用了freemarker做模板。

    具体代码如下

    import freemarker.template.Configuration;
    import freemarker.template.Template;
    import sun.misc.BASE64Encoder;
    
    import javax.servlet.ServletOutputStream;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    import java.io.*;
    import java.net.URLEncoder;
    import java.text.SimpleDateFormat;
    import java.util.Calendar;
    import java.util.Map;
    
    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 = "d:/我的项目/lm/lm/web/src/main/webapp/WEB-INF/templates";
    //    private static final String templateFolder =
        static {
            configuration = new Configuration();
            configuration.setDefaultEncoding("utf-8");
            try {
    //            configuration.setDirectoryForTemplateLoading(new File(templateFolder));
                configuration.setClassForTemplateLoading(WordUtils.class, "/template/");//模板文件所在路径
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    
        private WordUtils() {
            throw new AssertionError();
        }
    
        /**
         * 具体导出功能
         * @param request
         * @param response
         * @param map 具体数据
         * @param title 导出的文件名
         * @param ftlFile word模板ftl名称,对应静态代码快中:模板文件所在路径下的ftl文件
         * @throws IOException
         */
        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");
                // 设置浏览器以下载的方式处理该文件名
                Calendar cal = Calendar.getInstance();
                SimpleDateFormat f = new SimpleDateFormat("yyyyMMddhhmmss");
                String fileName = title + f.format(cal.getTime()) + ".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);
                }
            } catch(Exception e){
                e.printStackTrace();
            }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;
        }
    
        //获得图片的base64码
        @SuppressWarnings("deprecation")
        private static String getImageBase(String src, HttpServletRequest request, HttpServletResponse response) {
            if(src==null||src==""){
                return "";
            }
            File file = new File(request.getRealPath("/")+src.replace(request.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);
        }
    }
    View Code

    作为一个工具类,调用还是很简单的,自己构建数据后,在控制器端一行代码就可以了。

    WordUtils.exportMillCertificateWord(request, response, outMap, testpager.getTPNAME(), "exportword.ftl");

    其中outMap就是自己的数据,map键值对,在模板中通过${key}显示,其中判断语句,循环语句等需要参考freemarker的具体写法。

    需要说明的是:

    1、工具类中直接写入了response对象,所以在controller中调用需要返回void。

    2、注意引入模板时的路径问题。

    configuration.setDirectoryForTemplateLoading(new File(templateFolder));
    configuration.setClassForTemplateLoading(WordUtils.class, "/template/");//模板文件所在路径

    都可以引入路径,第一种是绝对路径,第二种是相对路径,代码中用了第二种。找到静态资源的template文件夹下的模板文件。

    总的说没技术含量,但是ftl模板没有预览,调试很麻烦,网上查也灭有好的方法,希望看官能够提供更好的方式。

  • 相关阅读:
    bzoj1415 NOI2005聪聪和可可
    Tyvj1952 Easy
    poj2096 Collecting Bugs
    COGS 1489玩纸牌
    COGS1487 麻球繁衍
    cf 261B.Maxim and Restaurant
    cf 223B.Two Strings
    cf 609E.Minimum spanning tree for each edge
    cf 187B.AlgoRace
    cf 760B.Frodo and pillows
  • 原文地址:https://www.cnblogs.com/PPBoy/p/10535780.html
Copyright © 2011-2022 走看看