freemarker word 导出类似于简历,人员档案,涉及图片压缩等

一、通过反射将所需要的属性设置到需要的占位符

package com.hisense.smartroad.common.util;

import java.lang.reflect.Field;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.time.DateFormatUtils;

/**
 * 反射工具类
 * @author xl
 *
 */
public class ReflectUtils {
	
	private static final String YYYY_MM_DD = "yyyy-MM-dd"; 
	private static final String YYYY_MM_DD_HH_MM_SS = "yyyy-MM-dd hh:mm:ss"; 
	private ReflectUtils(){}
	
	/**
	 * 反射设置属性和值,用于导出
	 * partten : 时间格式化
	 */
	public static Map<String,Object> setReflectValue(Object obj,String partten){
		Map<String,Object> map = new HashMap<>();
		try {
			Class clazz = obj.getClass() ;
			Field[] fs = clazz.getDeclaredFields();
			for (Field field : fs) {
				field.setAccessible(true);//设置能够访问私有方法
				if("serialVersionUID".equals(field.getName())){
					continue;
				}
				if (field.getType().equals("Date")) {
					String date = DateFormatUtils.format((Date)field.get(obj), YYYY_MM_DD); 
					if (!StringUtils.isEmpty(partten)) {
						date = DateFormatUtils.format((Date)field.get(obj), partten);
					}
					map.put(field.getName(), date);
					continue;
				}
				System.out.println(field.getName() + ":::::::::::::::::::::" + field.get(obj));
				map.put(field.getName(), field.get(obj)==null ? "" : field.get(obj));
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
	
		return map;
	}
}

二、前台向后台跳转的controller

package com.hisense.smartroad.saf.dangersource.controller;

import java.io.ByteArrayOutputStream;
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.HttpURLConnection;
import java.net.URL;
import java.net.URLEncoder;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

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

import org.hibernate.transform.Transformers;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.RequestMapping;

import com.hisense.smartroad.common.dao.SysDicDao;
import com.hisense.smartroad.common.util.FileUtil;
import com.hisense.smartroad.common.util.ReflectUtils;
import com.hisense.smartroad.saf.dangersource.dao.SafTDangerObjDao;
import com.hisense.smartroad.saf.dangersource.entity.SafTDangerAudi;
import com.hisense.smartroad.saf.dangersource.entity.SafTDangerObj;
import com.hisense.smartroad.saf.dangersource.service.SafTDangerObjService;

import freemarker.template.Configuration;
import freemarker.template.DefaultObjectWrapper;
import freemarker.template.Template;
import freemarker.template.TemplateException;


@Controller
@RequestMapping("/expDangerSouceZip")
public class DangersourceZipController {
	@Autowired
	SafTDangerObjService dangerService;
	@Autowired
	SysDicDao sysDicDao;
	
	private FileUtil fileutil;
	
	private ReflectUtils reflectUtils;
	@Resource
	private SafTDangerObjDao safTDangerObjDao;
	public Map<String, Object> getDangerObjMap(String dangerObjId){
		String hql="from SafTDangerObj where delFlag='0' and dangerObjId = ?";
		SafTDangerObj dangerObj = safTDangerObjDao.findUnique(hql,dangerObjId);
		Map<String,Object> dataMap = reflectUtils.setReflectValue(dangerObj,null);
	    //附件
        List<Map<String, Object>> list = new ArrayList<Map<String,Object>>();   
        if (dangerObj.getSafTDangerAudiSet() != null && !dangerObj.getSafTDangerAudiSet().isEmpty()) {
			for (SafTDangerAudi audit : dangerObj.getSafTDangerAudiSet()) {
				Map<String,Object> map = reflectUtils.setReflectValue(audit,"yyyy-MM-dd hh:mm:ss");
				map.put("auditNumber", list.size());
	            list.add(map);
			}
		}  
        dataMap.put("recordList",list);
        return dataMap;
	}

}

三、word 导出工具类,包含创建word,压缩图片等方法

package com.hisense.smartroad.common.util;

import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.image.BufferedImage;
import java.io.BufferedInputStream;
import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.UnsupportedEncodingException;
import java.io.Writer;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLEncoder;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

import javax.imageio.ImageIO;
import javax.imageio.stream.ImageOutputStream;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import net.sf.json.JSONObject;

import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.Resource;
import org.springframework.core.io.support.PropertiesLoaderUtils;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;

import freemarker.template.Configuration;
import freemarker.template.DefaultObjectWrapper;
import freemarker.template.Template;
import freemarker.template.TemplateException;

/**
 * 文档下载工具类
 * @author hp
 *
 */
@Component
public class ExpWordUtil {
	
	private ExpWordUtil(){}
	
	/**
	 * 附件ZIP下载
	 * @param url 接口地址
	 * @param fileName 附件名称
	 * urls : Map<String, String> MAP  fileName: 文件名称,   fileUrl :  文件下载路径
	 * 
	 */
	public void exportZip(HttpServletRequest request, HttpServletResponse response,
			List<Map<String, String>> urls,String zipName){
		ByteArrayOutputStream bos = null;
		ZipOutputStream zos = null;
		ServletOutputStream os = null;
		try {
			bos = new ByteArrayOutputStream();
			zos = new ZipOutputStream(bos);	
			for (int i = 0; i < urls.size(); i++) {
				zos.putNextEntry(new ZipEntry(i + "" + urls.get(i).get("fileName")));
				byte[] bytes = downURL(urls.get(i));
				zos.write(bytes, 0, bytes.length);
				zos.closeEntry();
			}		
			String fileName = new String((zipName + ".zip").getBytes("UTF-8"),
					"ISO8859-1");
			zos.close();
			response.setContentType("application/force-download");
			response.addHeader("content-disposition", "attachment;filename="
					+ fileName);
			os = response.getOutputStream();
			os.write(bos.toByteArray());
		
		} catch (Exception e) {
			e.printStackTrace();
		}finally{
			try {
				os.close();
				zos.close();
				bos.close();
			} catch (Exception e2) {
				e2.printStackTrace();
			}
		
		}
	}
	
	/**
	 * 文件下载 : 接口文件下载
	 * @param url 接口地址
	 * @param fileName 附件名称
	 */
	public void exportWord(HttpServletRequest request, HttpServletResponse response,
			String url,String fileName){
        InputStream fin = null;  
        OutputStream out = null;
        InputStream inputStream = null; 
        HttpURLConnection conn = null;
		try {
		    //获取网络输入流
		    inputStream = readInputStreamByURL(url);
		    String codedFileName = encodingFileName(fileName);
			response.setHeader("content-disposition", "attachment;filename="+ codedFileName); 
			fin = new BufferedInputStream(inputStream);   
		    out = response.getOutputStream();  

	        byte[] buffer = new byte[4096];  // 缓冲区  
	        int bytesToRead = -1;  
	            // 通过循环将读入的Word文件的内容输出到浏览器中  
	        while((bytesToRead = fin.read(buffer)) != -1) {  
	            out.write(buffer, 0, bytesToRead);  
	        }  
		} catch (Exception e) {
			e.printStackTrace();
		} finally{
			try {
				inputStream.close();
				fin.close();
				conn.disconnect();
				out.close();
			} catch (Exception e2) {
				e2.printStackTrace();
			}
			
		}

	}
	
	/**
	 * 模版下载
	 * @param dataMap 向模板内插入数据的MAP
	 * @param fileName 文件名称
	 * @param templateName 模板名称
	 */
	public  void exportWord(HttpServletRequest request,HttpServletResponse response,Map<String, Object> dataMap,String fileName,String templateName) throws Exception {
	    HttpSession session = request.getSession();
		session.setAttribute("state", null);
		// 生成提示信息,
		response.setContentType("application/msword");
		String codedFileName = null;
		File file = null;  
        InputStream fin = null;  
        OutputStream out = null; 
		try {	
			codedFileName = encodingFileName(fileName);
			response.setHeader("content-disposition", "attachment;filename="+ codedFileName);
			file =createWord(request,dataMap,templateName);  
            fin = new FileInputStream(file);  
            out = response.getOutputStream();  
            byte[] buffer = new byte[512];  // 缓冲区  
            int bytesToRead = -1;  
            // 通过循环将读入的Word文件的内容输出到浏览器中  
            while((bytesToRead = fin.read(buffer)) != -1) {  
                out.write(buffer, 0, bytesToRead);  
            }  
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			if(fin != null) fin.close();  
          if(out != null) out.close();  
          if(file != null) file.delete(); // 删除临时文件  
			session.setAttribute("state", "open");
		}
		System.out.println("文件生成...");
  }
  
	/**
	 * 主要设置reponse 流的setheader时的名称
	 * @param fileName 需要下载的名称
	 */
	public static String encodingFileName(String fileName) {
      String returnFileName = "";
      try {
          returnFileName = URLEncoder.encode(fileName, "UTF-8");
          returnFileName = StringUtils.replace(returnFileName, "+", "%20");
          if (returnFileName.length() > 0) {
              returnFileName = new String(fileName.getBytes("GB2312"), "ISO8859-1");
              returnFileName = StringUtils.replace(returnFileName, " ", "%20");
          }
      } catch (UnsupportedEncodingException e) {
          e.printStackTrace();
      }
      return returnFileName;
  }
  /**
	 * 从request中获得参数Map,并返回可读的Map
	 * 
	 * @param request
	 * @return
	 */
	@SuppressWarnings("unchecked")
	public static Map getParameterMap(HttpServletRequest request) {
	    // 参数Map
	    Map<String,String> properties = request.getParameterMap();
	    // 返回值Map
	    Map<String, Object> returnMap = new HashMap<String, Object>();
	    if(properties==null || properties.isEmpty()) return returnMap;
	    Iterator entries = properties.entrySet().iterator();
	    Map.Entry entry;
	    String name = "";
	    String value = "";
	    while (entries.hasNext()) {
	        entry = (Map.Entry) entries.next();
	        name = (String) entry.getKey();
	        Object valueObj = entry.getValue();
	        if(null == valueObj){
	            value = "";
	        }else if(valueObj instanceof String[]){
	            String[] values = (String[])valueObj;
	            for(int i=0;i<values.length;i++){
	                value = values[i] + ",";
	            }
	            value = value.substring(0, value.length()-1);
	        }else{
	            value = valueObj.toString();
	        }
	        returnMap.put(name, value);
	    }
	    return returnMap;
	}
	
	/**
	 * @Description: 创建Word临时文件
	 * @author zhuhuiling
	 * @param request 
	 * @throws Exception 
	 * @date 2017-10-11 
	 */
	public File createWord(HttpServletRequest request,Map<String, Object> dataMap,String templateName) throws Exception{
		File file=new File(System.currentTimeMillis()+"");
		Configuration con = new Configuration();
		Writer out = null;
		try {  
			con.setServletContextForTemplateLoading(request.getSession()
					.getServletContext(), "/resources/template");
			con.setObjectWrapper(new DefaultObjectWrapper());// 指定生产模板的方式
			con.setDefaultEncoding("utf-8");// 设置模板读取的编码方式,用于处理乱码
			Template template = con.getTemplate(templateName);// 模板文件,可以是xml,ftl,html
			System.out.println(template.getEncoding());
			template.setObjectWrapper(new DefaultObjectWrapper());// 指定生产模板的方式
			template.setEncoding("utf-8");// 设置写入模板的编码方式
            // 这个地方不能使用FileWriter因为需要指定编码类型否则生成的Word文档会因为有无法识别的编码而无法打开  
            out = new OutputStreamWriter(new FileOutputStream(file), "utf-8");  
            template.process(dataMap, out);  
            out.close();  
        } catch (IOException e) {
			e.printStackTrace();
		} catch (TemplateException e) {
			e.printStackTrace();
		}finally {
			try {
				out.flush();
				out.close();
			} catch (IOException e) {
			}
		}
		return file;
	}
	
	
	/**
	 * 读取URL中结果集
	 */
	private byte[] downURL(Map<String, String> map) throws Exception {

		byte[] data = null;
		InputStream is = null;
		HttpURLConnection conn = null;
		URL url = new URL(map.get("fileUrl"));
		conn = (HttpURLConnection) url.openConnection();
		conn.setDoInput(true);
		conn.setRequestMethod("GET");
		conn.setConnectTimeout(6000);
		is = conn.getInputStream();
		if (conn.getResponseCode() == 200) {
			data = readInputStream(is);
		} else {
			data = null;
		}
		is.close();
		conn.disconnect();
		return data;
	}
	
	/**
	 * 读取流程
	 */
	private byte[] readInputStream(InputStream is) throws Exception {
		ByteArrayOutputStream baos = new ByteArrayOutputStream();
		byte[] buffer = new byte[1024];
		int length = -1;
		while ((length = is.read(buffer)) != -1) {
			baos.write(buffer, 0, length);
		}
		baos.flush();
		byte[] data = baos.toByteArray();
		is.close();
		baos.close();

		return data;
	}
	
	/**
	 * 用于word图片下载
	 * 根据fileID获取文件流
	 * FILE_URL = "http://10.60.5.7/DOC/dorado/uploader/filehandle?_fileProvider=sinUploadProcessor%23detail&fileid=";
	 */
	public InputStream readInputStreamByFileId(String fileId){
		Properties props = new Properties();
		Resource resource = new ClassPathResource("uploader.properties");
		InputStream inputStream = null;
		try {
			props = PropertiesLoaderUtils.loadProperties(resource);
			String  props_url= props.getProperty("u.url");
			StringBuffer url = new StringBuffer(props_url.substring(0, props_url.length() -10) 
					+ "filehandle?_fileProvider=sinUploadProcessor%23detail&fileid=");
			url.append(fileId);  //下载地址拼接
		    //获取网络输入流
		    inputStream  = readInputStreamByURL(url.toString());		    
		    BufferedReader bf = new BufferedReader(new InputStreamReader(inputStream,"UTF-8"));
		    String line = null;
		    while((line=bf.readLine())!=null){//一行一行的读 
		    	JSONObject json = new JSONObject();  
		    	json = json.fromObject(line);
		    	JSONObject data = (JSONObject) json.get("data");
		    	JSONObject file = (JSONObject) data.get(fileId);
		    	String fileUrl = file.get("file_url") + ""; //图片下载地址
		    	inputStream =  readInputStreamByURL(fileUrl); //图片流
		    	inputStream = compressImage(inputStream,140,100); //压缩图片流
		    }		    
		} catch (Exception e) {
			System.out.println(e);
		}
		return inputStream;

	}
	
	/**
	 * 压缩图片
	 */
	public InputStream compressImage(InputStream inputStream,int width,int height){
		try {
			Image src = ImageIO.read(inputStream); 
			int h = (int)(src.getHeight(null)); 
			int w = (int)(src.getWidth(null));
			//重构图片 
            double bili; 
            if(width > 0){ 
                bili = width/(double)w; 
                height = (int) (h * bili); 
            }else{ 
                if(height > 0){ 
                    bili = height/(double)h; 
                    width = (int) (w * bili); 
                } 
            } 
            //重构图片 
			BufferedImage bufferedImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
            Graphics2D graphics = bufferedImage.createGraphics(); 
			graphics.drawImage(src, 0, 0, width, height, null); 
			ByteArrayOutputStream bs =new ByteArrayOutputStream(); 
			ImageOutputStream imOut =ImageIO.createImageOutputStream(bs); 
			ImageIO.write(bufferedImage,"png",imOut); 
			//将图片转为inputStream流 
			return new ByteArrayInputStream(bs.toByteArray());
		} catch (Exception e) {
			e.printStackTrace();
		}
		return null;
	}
	
	/**
	 * 获取文件流
	 * @param url 导出URL
	 * @return
	 */
	private InputStream readInputStreamByURL(String url){
		InputStream inputStream = null;
		try {
			HttpURLConnection httpURLConnection = null;
			URL httpUrl=new URL(url);
			httpURLConnection=(HttpURLConnection) httpUrl.openConnection();
			//以Post方式提交表单,默认get方式
			httpURLConnection.setRequestMethod("GET");
			httpURLConnection.setDoInput(true);  
			httpURLConnection.setDoOutput(true);
	
			httpURLConnection.setUseCaches(false);
		    //连接指定的资源 
			httpURLConnection.connect();
			//获取网络输入流
			inputStream =  httpURLConnection.getInputStream();
		} catch (IOException e) {
			e.printStackTrace();
		}
		return inputStream;
	}
}

四、freemarker模板

 

### 回答1: Freemarker可以通过使用Apache POI库来导出带有图片的Word文档。首先,需要在模板中定义一个图片占位符,然后在Java代码中将图片插入到占位符中。具体步骤如下: 1. 在Word模板中定义一个图片占位符,例如:${image}。 2. 在Java代码中,使用Apache POI库加载模板文件,并获取到模板中的图片占位符。 3. 使用POI的XWPFRun类创建一个新的段落,并将图片插入到段落中。 4. 将段落插入到模板中的图片占位符位置。 5. 保存生成的Word文档。 示例代码如下: ``` // 加载模板文件 FileInputStream fis = new FileInputStream("template.docx"); XWPFDocument doc = new XWPFDocument(fis); // 获取图片占位符 XWPFParagraph imagePlaceholder = doc.getParagraphs().stream() .filter(p -> p.getText().contains("${image}")) .findFirst().orElse(null); // 创建新的段落 XWPFParagraph newParagraph = doc.createParagraph(); // 插入图片到段落中 XWPFRun newRun = newParagraph.createRun(); newRun.addPicture(new FileInputStream("image.jpg"), XWPFDocument.PICTURE_TYPE_JPEG, "image.jpg", Units.toEMU(200), Units.toEMU(200)); // 将段落插入到图片占位符位置 int index = doc.getPosOfParagraph(imagePlaceholder); doc.removeBodyElement(index); doc.setParagraph(newParagraph, index); // 保存生成的Word文档 FileOutputStream fos = new FileOutputStream("output.docx"); doc.write(fos); fos.close(); ``` 注意:在使用POI插入图片时,需要指定图片的类型和大小。示例代码中使用的图片类型为JPEG,大小为200x200像素。 ### 回答2: Freemarker是一种模板引擎,可以将数据和模板结合生成静态文本,并且常见在Spring框架中使用。而导出Word带有图片,一般需要通过POI或者Apache POI来实现,具体步骤如下: 1.首先需要引入POI和Freemarker的jar包。 2.在模板中添加图片的占位符,例如${logo}。 3.通过Java代码将图片读入到输出流中,然后在模板中替换${logo}的内容为图片字节数组的Base64编码。 4.通过Freemarker将数据和模板结合,生成Word文件。 5.最后需要使用POI将Word文件的后缀名由.ftl改为.doc或.docx,并且编写下载逻辑进行下载。 需要注意的是,在将图片插入Word文档时,可能出现图片比例失调或者无法插入图片的情况,这时需要调整插入图片的方式,可以将图片插入一个模板中,然后将模板插入到Word文档中,以保证插入的图片比例正确。 ### 回答3: FreeMarker是一种Java模板引擎,它允许使用模板生成文本输出,其中包括MS Word文档。在导出word带图片时,需要使用FreeMarker的JDBC模式来检索数据和图片,然后将它们插入Word文档中。以下是导出Word带图片的步骤: 1.准备Word模板:首先需要创建一个Word模板,包含需要添加文本的区域和占位符来插入图片。这可以通过在Word中创建一个新文档,添加文本和占位符,然后保存为docx文件来完成。 2.准备模板数据:使用Java代码从数据库中检索需要导出的数据和图片,并将它们作为数据模型引入FreeMarker模板引擎中。 3.将数据模型应用于模板:使用FreeMarker模板引擎将数据模型应用于Word模板中,并生成将要输出的Word文档。 4.插入图片:通过在FreeMarker模板中使用图片占位符,将图片插入到生成的Word文档中。这可以通过将图片从数据库中检索出来并使用二进制方式插入模板中来完成。 5.保存Word文档:完成所有文本和图片的插入后,将生成的Word文档保存到文件系统或输出流中即可。 在使用FreeMarker导出Word带图片时,需要注意以下几点: 1.在Word模板中应该包含正确的占位符并设置样式和布局。 2.从数据库中检索图片时应该压缩和缩放图片以确保它们适合文档中的区域。 3.在插入图片时,正确处理可能出现的图片格式和分辨率问题。 4.应对可能出现的异常情况进行处理,以确保生成的Word文档具有良好的稳定性和可靠性。 总之,使用FreeMarker导出Word带图片是一项需要谨慎处理的复杂任务。通过遵循以上步骤和注意事项,可以生成具有高质量和稳健性的Word文档并满足客户的需求。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值