zoukankan      html  css  js  c++  java
  • JAVAWEB使用FreeMarker利用ftl把含有图片的word模板生成word文档,然后打包成压缩包进行下载

    这是写的另一个导出word方法:https://www.cnblogs.com/pxblog/p/13072711.html

    引入jar包,freemarker.jar、apache-ant-zip-1.8.0.jar(制作压缩包使用)

    下载地址:   https://yvioo.lanzous.com/b00njhxoh    密码:2mcs

    或者maven

    <!-- https://mvnrepository.com/artifact/org.freemarker/freemarker -->
    <dependency>
        <groupId>org.freemarker</groupId>
        <artifactId>freemarker</artifactId>
        <version>2.3.23</version>
    </dependency>
    <!-- https://mvnrepository.com/artifact/org.apache.ant/ant -->
    <dependency>
        <groupId>org.apache.ant</groupId>
        <artifactId>ant</artifactId>
        <version>1.8.0</version>
    </dependency>

    1、准备ftl模板,先在一个word中模板排版好,然后另存为-保存成“Word 2003 XML文档” 后缀名是.xml的文件

    注:模板中的值要使用占位符进行填充 ,如下图所示,“name”名称是根据后台代码来的,这里可以换成自己的

    然后生成.xml文件后,可以利用网上格式化工具格式化看下 生成的模板文件是否正确,占位符“${name}”必须是完整的,中间不能含有其他字符

     如果word模板中含有图片,图片在xml文件中展现的形式是Base64格式的 ,包含在<w:binData>和</w:binData>中,把Base64删掉,替换成占位符,我这里使用的是“${photo}”(<w:binData>和</w:binData>中除了占位符不能有其他代码,也不能换行,主要是下面两个标签内都不能有其他标签)

    如果没有<w:binData>和</w:binData>标签的话,就是在模板中没有把图片放进去,需要把图片也放进去模板中,然后生成xml文件

    <w:binData w:name="wordml://03000001.png" xml:space="preserve">${photo}</w:binData>
    <v:shape id="图片 2" o:spid="_x0000_i1025" type="#_x0000_t75" style="56.5pt;height:93pt;visibility:visible;mso-wrap-style:square"><v:imagedata src="wordml://03000001.png" o:title="touxiangm"/></v:shape>

     如果是多张图片的时候,就在模板文档里面放多张图片,然后看生成的模板样子,内容都是可以循环的,把共同部分拿出来,然后使用<#list>标签进行循环遍历,有些字段循环也是不一样,如下图所示,每个人可能模板不一样。

     

    2、然后把保存的wordExport.xml文件 后缀名改成.ftl文件 

    3、后台代码

    导出word工具类

    WordUtils.javapackage testword;
    import java.io.*;
    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;
    import sun.misc.BASE64Encoder;
    
    public class WordUtils {
        //配置信息,代码本身写的还是很可读的,就不过多注解了
        private static Configuration configuration = null;
        //这里注意的是利用WordUtils的类加载器动态获得模板文件的位置
        // private static final String templateFolder = WordUtils.class.getClassLoader().getResource("../../").getPath() + "WEB-INF/templetes/";
    
    
        public  File exportMillCertificateWord(HttpServletRequest request, HttpServletResponse response, Map map,String title,String templateFolder,String toDirFloder) throws IOException {
            configuration = new Configuration();
            configuration.setDefaultEncoding("utf-8");
            
            //模板所在文件夹
            configuration.setDirectoryForTemplateLoading(new File(templateFolder));
            //wordExport.ftl为模板文件名称
            Template freemarkerTemplate = configuration.getTemplate("wordExport.ftl");
            File file = null;
            InputStream fin = null;
            ServletOutputStream out = null;
            // 调用工具类的createDoc方法生成Word文档
            file = createDoc(map,freemarkerTemplate,title,toDirFloder);
            return file;
        }
    
        private static File createDoc(Map<?, ?> dataMap, Template template,String filename,String toDirFloder) {
    File f
    = new File(toDirFloder+"/"+filename+".doc"); 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; } public String getImageBase(String src) { if(src==null||src==""){ return ""; } File file = new File(src); 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); } }

    导出压缩包工具类

    Zipper.java

    package testword;
    
    import org.apache.commons.lang.StringUtils;
    import org.apache.tools.zip.ZipEntry;
    import org.apache.tools.zip.ZipOutputStream;
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    import org.springframework.util.Assert;
    
    import java.io.*;
    import java.util.List;
    
    /**
     * 用于制作zip压缩包
     */
    public class Zipper {
        private static final Logger log = LoggerFactory.getLogger(Zipper.class);
    
        /**
         * 制作压缩包
         * 
         */
        public static void zip(OutputStream out, List<FileEntry> fileEntrys,
                String encoding) {
            new Zipper(out, fileEntrys, encoding);
        }
    
        /**
         * 制作压缩包
         * 
         */
        public static void zip(OutputStream out, List<FileEntry> fileEntrys) {
            new Zipper(out, fileEntrys, null);
        }
    
        /**
         * 创建Zipper对象
         * 
         * @param out
         *            输出流
         * @param filter
         *            文件过滤,不过滤可以为null。
         * @param srcFilename
         *            源文件名。可以有多个源文件,如果源文件是目录,那么所有子目录都将被包含。
         */
        protected Zipper(OutputStream out, List<FileEntry> fileEntrys,
                         String encoding) {
            Assert.notEmpty(fileEntrys);
            long begin = System.currentTimeMillis();
            log.debug("开始制作压缩包");
            try {
                try {
                    zipOut = new ZipOutputStream(out);
                    if (!StringUtils.isBlank(encoding)) {
                        log.debug("using encoding: {}", encoding);
                        zipOut.setEncoding(encoding);
                    } else {
                        log.debug("using default encoding");
                    }
                    for (FileEntry fe : fileEntrys) {
                        zip(fe.getFile(), fe.getFilter(), fe.getZipEntry(), fe
                                .getPrefix());
                    }
                } finally {
                    zipOut.close();
                }
            } catch (IOException e) {
                throw new RuntimeException("制作压缩包时,出现IO异常!", e);
            }
            long end = System.currentTimeMillis();
            log.info("制作压缩包成功。耗时:{}ms。", end - begin);
        }
    
        /**
         * 压缩文件
         * 
         * @param srcFile
         *            源文件
         * @param pentry
         *            父ZipEntry
         * @throws IOException
         */
        private void zip(File srcFile, FilenameFilter filter, ZipEntry pentry,
                String prefix) throws IOException {
            ZipEntry entry;
            if (srcFile.isDirectory()) {
                if (pentry == null) {
                    entry = new ZipEntry(srcFile.getName());
                } else {
                    entry = new ZipEntry(pentry.getName() + "/" + srcFile.getName());
                }
                File[] files = srcFile.listFiles(filter);
                for (File f : files) {
                    zip(f, filter, entry, prefix);
                }
            } else {
                if (pentry == null) {
                    entry = new ZipEntry(prefix + srcFile.getName());
                } else {
                    entry = new ZipEntry(pentry.getName() + "/" + prefix
                            + srcFile.getName());
                }
                FileInputStream in;
                try {
                    log.debug("读取文件:{}", srcFile.getAbsolutePath());
                    in = new FileInputStream(srcFile);
                    try {
                        zipOut.putNextEntry(entry);
                        int len;
                        while ((len = in.read(buf)) > 0) {
                            zipOut.write(buf, 0, len);
                        }
                        zipOut.closeEntry();
                    } finally {
                        in.close();
                    }
                } catch (FileNotFoundException e) {
                    throw new RuntimeException("制作压缩包时,源文件不存在:"
                            + srcFile.getAbsolutePath(), e);
                }
            }
        }
    
        private byte[] buf = new byte[1024];
        private ZipOutputStream zipOut;
    
        public static class FileEntry {
            private FilenameFilter filter;
            private String parent;
            private File file;
            private String prefix;
    
            public FileEntry(String parent, String prefix, File file,
                    FilenameFilter filter) {
                this.parent = parent;
                this.prefix = prefix;
                this.file = file;
                this.filter = filter;
            }
    
            public FileEntry(String parent, File file) {
                this.parent = parent;
                this.file = file;
            }
    
            public FileEntry(String parent, String prefix, File file) {
                this(parent, prefix, file, null);
            }
    
            public ZipEntry getZipEntry() {
                if (StringUtils.isBlank(parent)) {
                    return null;
                } else {
                    return new ZipEntry(parent);
                }
            }
    
            public FilenameFilter getFilter() {
                return filter;
            }
    
            public void setFilter(FilenameFilter filter) {
                this.filter = filter;
            }
    
            public String getParent() {
                return parent;
            }
    
            public void setParent(String parent) {
                this.parent = parent;
            }
    
            public File getFile() {
                return file;
            }
    
            public void setFile(File file) {
                this.file = file;
            }
    
            public String getPrefix() {
                if (prefix == null) {
                    return "";
                } else {
                    return prefix;
                }
            }
    
            public void setPrefix(String prefix) {
                this.prefix = prefix;
            }
        }
    }

    使用控制器类

    package testword;
    
    import org.springframework.web.bind.annotation.RequestMapping;
    
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    import java.io.File;
    import java.io.IOException;
    import java.util.ArrayList;
    import java.util.HashMap;
    import java.util.List;
    import java.util.Map;
    
    public class TestWord {
    
        @RequestMapping("/o_export")
        public void export(HttpServletRequest request, HttpServletResponse response) {
            WordUtils wordUtils = new WordUtils();
            List<Zipper.FileEntry> flist = new ArrayList<Zipper.FileEntry>();
    
            //这里要获取要导出的数据列表集合
            List list = null;
            //模板所在文件夹路径
            String tplDir = null;
    //模板word临时存储的位置
    String toDirFloder=null

          //文件夹不存在,创建文件夹
          File dirFile=new File(toDirFloder);
          if (!dirFile.exists()){
            dirFile.mkdirs();
          }

            //要循环遍历的数据
            for (Object e : list) {
                //导出的word文件名称
                String filename = null;
                try {
                    File file = wordUtils.exportMillCertificateWord(request, response, enrollToMap(e, wordUtils), filename, tplDir, toDirFloder);
                    //这里表示压缩包下会有一个文件夹,名称是“学生信息表”,所有的word文件会放到这个文件夹底下
                    Zipper.FileEntry entry = new Zipper.FileEntry("学生信息表", file);
                    //把文件放到压缩包中
                    flist.add(entry);
                } catch (IOException e1) {
                    e1.printStackTrace();
                }
            }
            response.setContentType("application/x-download;charset=UTF-8");
            try {
                //这里的“学生信息表”是压缩包文件名
                response.addHeader("Content-disposition", "filename=" + new String("学生信息表".getBytes("gb2312"), "iso8859-1") + ".zip");
                Zipper.zip(response.getOutputStream(), flist, "GBK");

            //删除word临时保存的文件和文件夹
            File[] files=dirFile.listFiles();
            for (File f:files){
                f.delete();
            }
            dirFile.delete();

            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    
    
        public Map enrollToMap(Student s, WordUtils wordUtils) {
            Map map = new HashMap();
    
            //这里的name和sex为模板中占位符的名称 我模板中用的占位符是“${name}”,所以这里map集合的key是name
            map.put("name", s.getName());
            map.put("sex", s.getSex());
    
            //获取图片URL地址后,调用方法生成BASE64格式
            String photoBase64 = wordUtils.getImageBase("图片URL绝对地址");
            map.put("photo", photoBase64);
            return map;
        }
    }
  • 相关阅读:
    linux常用命令
    mysql 开发基础系列20 事务控制和锁定语句(上)
    sql server 性能调优之 资源等待 CXPACKET
    mysql 开发基础系列19 触发器
    mysql 开发基础系列18 存储过程和函数(下)
    mysql 开发基础系列17 存储过程和函数(上)
    sql server 性能调优之 资源等待PAGEIOLATCH
    mysql 开发基础系列16 视图
    mysql 开发基础系列15 索引的设计和使用
    sql server 性能调优之 当前用户请求分析 (1)
  • 原文地址:https://www.cnblogs.com/pxblog/p/12790904.html
Copyright © 2011-2022 走看看