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="width: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; } }

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM