java 将ftl文件作为模板导出word文档

     因为poi等输出word很麻烦,所以本文使用word编辑好模板,转成xml再转成ftl,在java中导入ftl模板,填充数据再生成为word下载或保存。

一、模板文档

1、在Word中编辑好word模板,变量部分用el表达式替代


2、另存为xml文件(2003),打开xml文件,讲 sellerName等改为el表达式:${sellerName!}等,然后将.xml文件后缀改为.ftl,把.ftl模板文件到项目制定目录。加载jar包freemarker.jar然后开始后端代码


二、后台主要代码

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.UnsupportedEncodingException;
import java.io.Writer;
import java.net.URLEncoder;
import java.util.Map;
import java.util.Properties;

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

import org.apache.commons.lang3.StringUtils;
import org.springframework.util.ClassUtils;

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

/**
 * word模板工具类
* <p>Title: WordGenerator</p>  
* <p>Description: </p>  
* @author terry.peng
 */
public class WordGenerator { 
	private static Configuration configuration=null; 
	//private static final String templateFolder = WordGenerator.class.getClass().getResource("").getPath()+"/ftl/";  
	//private static final String templateFolder = WordGenerator.class.getClass().getResource("/" + ClassUtils.convertClassNameToResourcePath(WordGenerator.class.getPackage().getName())).getFile() + "/ftl";
	private static final String templateFolder = "D:/ftl";
	static{ 
		configuration=new Configuration(); 
		configuration.setDefaultEncoding("utf-8"); 
		try { 
			configuration.setDirectoryForTemplateLoading(new File(templateFolder));
		} catch (IOException e) { 
			e.printStackTrace();//throw new RuntimeException(e); 
		} 
	} 
	
	private WordGenerator() { 
		throw new AssertionError(); 
	} 
	
	/**
	 * 下载合同
	 * @param map 要填充的数据模型
	 * @param docName 下载保存的名称(例如:销售合同.doc)
	 * @param ftlFile ftl模板名称(例如:sellerContract.ftl)
	 * @throws Exception
	 */
	public static void downContract(HttpServletRequest request, HttpServletResponse response, Map<?, ?> map,String docName,String ftlFile) throws Exception {  
		File file = null;  
		FileInputStream fin = null;  
        ServletOutputStream out = null;  
        try {
        	setDownloadHeader(request, response, docName);//设置下载头
	        
	        // 调用工具类的createDoc方法生成Word文档  
	        file = createDoc(request,response,map,docName,ftlFile);  
	        fin = new FileInputStream(file.getAbsolutePath());  
	        out = response.getOutputStream();  
	        int len = 0;
			byte[] buf = new byte[1024];
			while ((len = fin.read(buf)) != -1) {
				out.write(buf, 0, len);
			}
			out.flush();
		} catch (Exception e) {
			response.setStatus(HttpServletResponse.SC_NOT_FOUND);
			throw new Exception(e.getMessage(), e);
        } finally {  
            if(fin != null) {
            	try {
					fin.close();
				} catch (Exception e) {
					e.printStackTrace();
				}
            }  
            if(out != null) {
            	 try {
					out.close();
				} catch (Exception e) {
					e.printStackTrace();
				} 
            } 
            if(file != null) {
            	try {
					file.delete();// 删除临时文件  
				} catch (Exception e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
            }  
        }  
    }
	
	/**
	 * 导入ftl并创建doc 
	 * @param request
	 * @param response
	 * @param dataMap
	 * @param docName
	 * @param ftlFile
	 * @return
	 * @throws IOException
	 */
	public static File createDoc(HttpServletRequest request, HttpServletResponse response,Map<?, ?> dataMap, String docName,String ftlFile) throws IOException { 
		Template template = configuration.getTemplate(ftlFile);
		String name = templateFolder + File.separator + (int) (Math.random() * 100000) + docName; 
		File file = new File(name); 
		try { // 这个地方不能使用FileWriter因为需要指定编码类型否则生成的Word文档会因为有无法识别的编码而无法打开 
			Writer writer = new OutputStreamWriter(new FileOutputStream(file), "utf-8"); 
			template.process(dataMap, writer); 
			// 关闭流
			writer.flush();
			writer.close(); 
		} catch (Exception ex) { 
			ex.printStackTrace();
		} 
		return file; 
	} 
	
	/** object转map
	 * <p>Title: objectToMap</p>  
	 * <p>Description: </p>  
	 * @param obj
	 * @return
	 */
	public static Map<?, ?> objectToMap(Object obj) {
	    if (obj == null) {
	      return null;
	    }
	    return new org.apache.commons.beanutils.BeanMap(obj);
	 }
	
	/**
	 * map转Object
	 * <p>Title: mapToObject</p>  
	 * <p>Description: </p>  
	 * @param map
	 * @param beanClass 
	 * @return
	 * @throws Exception
	 */
	public static Object mapToObject(Map<String, Object> map, Class<?> beanClass)
		      throws Exception {
	    if (map == null)
	      return null;
	    Object obj = beanClass.newInstance();
	    org.apache.commons.beanutils.BeanUtils.populate(obj, map);
	    return obj;
	}
	
	 /**
     * 
     * @param request
     * @param response
     * @param fileName
     */
    public static void setDownloadHeader(HttpServletRequest request, HttpServletResponse response, String fileName) {
    	 String userAgent = request.getHeader("User-Agent");
         boolean isIE = (userAgent != null) && (userAgent.toLowerCase().indexOf("msie") != -1);

         response.setHeader("Pragma", "No-cache");
         response.setHeader("Cache-Control", "must-revalidate, no-transform");
         response.setDateHeader("Expires", 0L);

         response.setContentType("application/x-download");
         
         try {
        	 if (isIE) {
            	 fileName = new String(fileName.getBytes("gb2312"), "iso-8859-1");
                 response.setHeader("Content-Disposition", "attachment;filename=\"" + fileName + "\"");
             } else {
            	 fileName = new String(fileName.getBytes("gb2312"), "iso-8859-1");
                 response.setHeader("Content-Disposition", "attachment;filename=" + fileName);
             }
		} catch (Exception e) {
			e.printStackTrace();
		}
    }
	
}

三、其他

ftl模板中取值可以用el表达式取值${username}

如果要迭代list,String[]、或者在模板中做其他逻辑处理等,可以直接写freemarker的语言,例如:

<![CDATA[<#if goodsAttr?? && (goodsAttr?size > 0)> <#list goodsAttr as g>${g!}<#if g_has_next>]]><w:br/><![CDATA[</#if></#list> </#if>]]>
<![CDATA[<#if tradeRemark?? && (tradeRemark?length gt 0)> <#list tradeRemark?split("\n") as g>${g!}<#if g_has_next>]]><w:br/><![CDATA[</#if></#list> </#if>]]></w:t>

在xml中写freemarker语言要用<![CDATA[   ]]>原样输出

word转成的xml回车符号为<w:br/>

效果为


本文出处:https://blog.youkuaiyun.com/pdy8023/article/details/80339414



评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值