【freemaker实现导出word②】代码实现导出word(包括导出list数据和导出图片到word)
前面文章已经分享了如何创建导出word需要用到的xml/ftl模板了,接下来这里要给大家分享的是如何用后台制作导出word的代码工具和controller实现。
1、首先是工具类,没有工具,谈何实现呢?下面贴我这边导出word的utils,大家可以直接复制粘贴到你们项目就可以引用了。
package com.*.util; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStreamWriter; import java.io.Writer; import java.util.Map; import javax.servlet.http.HttpServletRequest; import Decoder.BASE64Encoder; import freemarker.template.Configuration; import freemarker.template.Template; import freemarker.template.TemplateException; import freemarker.template.TemplateExceptionHandler; /** * 类名称:DocUtil * 类描述:导出word工具类 */ public class DocUtil { public Configuration configure=null; public DocUtil(){ configure= new Configuration(Configuration.getVersion()); configure.setDefaultEncoding("utf-8"); } /** * 根据Doc模板生成word文件 * @param dataMap 需要填入模板的数据 * @param downloadType 文件名称 * @param savePath 保存路径 */ public File createDoc(Map<String,Object> dataMap,String modelPath,String downloadType,HttpServletRequest request){ String name = "temp" + (int) (Math.random() * 100000) + ".doc"; File f = new File(name); //加载需要装填的模板 Template template=null; try { //设置模板装置方法和路径,FreeMarker支持多种模板装载方法。可以重servlet,classpath,数据库装载。 //加载模板文件,放在/uploadFiles/file/demoDoc下 configure.setServletContextForTemplateLoading(request.getServletContext(), modelPath); //设置对象包装器 // configure.setObjectWrapper(new DefaultObjectWrapper()); //设置异常处理器 configure.setTemplateExceptionHandler(TemplateExceptionHandler.IGNORE_HANDLER); //定义Template对象,注意模板类型名字与downloadType要一致 template=configure.getTemplate(downloadType); Writer out = new OutputStreamWriter(new FileOutputStream(f), "utf-8"); template.process(dataMap, out); out.close(); } catch (IOException e) { e.printStackTrace(); } catch (TemplateException e) { e.printStackTrace(); } return f; } /** * 根据Doc模板生成word文件 * @param dataMap 需要填入模板的数据 * @param downloadType 文件名称 * @param savePath 保存路径 */ public void createXls(Map<String,Object> dataMap,String downloadType,String webPath,String fileName,String savePath){ System.out.println(savePath.substring(savePath.length()-1)); if(savePath.substring(savePath.length()-1).equals(File.separator)) { savePath = savePath + "uploadFiles" + File.separator + "file" + File.separator + "jdhDailySheet"+ File.separator; }else { savePath = savePath + File.separator + "uploadFiles" + File.separator + "file" + File.separator + "jdhDailySheet"+ File.separator; } File f = new File(savePath+fileName); //加载需要装填的模板 Template template=null; try { if(!f.getParentFile().exists()){ f.getParentFile().mkdirs(); } if(f.exists() && f.isFile()){ f.delete(); } else { f.createNewFile(); } //设置模板装置方法和路径,FreeMarker支持多种模板装载方法。可以重servlet,classpath,数据库装载。 //加载模板文件,放在/uploadFiles/file/demoDoc下 configure.setDirectoryForTemplateLoading(new File(webPath + "uploadFiles" + File.separator + "file" + File.separator)); //设置对象包装器 // configure.setObjectWrapper(new DefaultObjectWrapper()); //设置异常处理器 configure.setTemplateExceptionHandler(TemplateExceptionHandler.IGNORE_HANDLER); //定义Template对象,注意模板类型名字与downloadType要一致 template=configure.getTemplate(downloadType); Writer out = new OutputStreamWriter(new FileOutputStream(f), "utf-8"); template.process(dataMap, out); out.close(); } catch (IOException e) { e.printStackTrace(); } catch (TemplateException e) { e.printStackTrace(); } } }
2、接下来是处理图片的工具类,这里导出word包含导出图片到word,所以需要对图片进行处理,是怎么个原理呢,在这里和大家简单介绍下,具体在后续我会具体详细另外写一篇文章分享。
(1)图片我们可以在前台将要的图片转成base64编码,然后提交给后台接收
(2)后台接收base64编码后使用工具类将base64解码成图片然后保存到本地中
(3)在要导出word的时候读取下本地存储图片的路径然后把图片导出来就行了。
工具类如下:同第一条一样可直接复制到你们项目中使用。
package com.*.util; import java.awt.image.BufferedImage; 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.OutputStream; import java.util.UUID; import javax.imageio.ImageIO; import Decoder.BASE64Decoder; import Decoder.BASE64Encoder; /** * 类名称:ImageUtil * 类描述:图片处理工具类 */ public class ImageUtil { /** * 从path这个地址获取一张图片然后转为base64码 * @param imgName 图片的名字 如:123.png(是带后缀的) * @param path 123.png图片存放的路径 * @return * @throws Exception */ public static String getImageFromServer(String imgName,String path)throws Exception{ BASE64Encoder encoder = new BASE64Encoder(); File f = new File(path+imgName); if(!f.exists()){ f.createNewFile(); } BufferedImage bi = ImageIO.read(f); ByteArrayOutputStream baos = new ByteArrayOutputStream(); ImageIO.write(bi, "png", baos); byte[] bytes = baos.toByteArray(); return encoder.encodeBuffer(bytes).trim(); } /** * 将一个base64转换成图片保存在 path文件夹下 ,命名随机 * @param base64String * @param path 是一个文件夹路径 * @param imgName 图片名字(没有后缀) * @throws Exception */ public static String savePictoServer(String base64String,String path)throws Exception{ BASE64Decoder decoder = new BASE64Decoder(); //要把+在上传时变成的空格再改为+ base64String = base64String.replaceAll(" ", "+"); //去掉“data:image/png;base64,”后面才是base64编码,去掉之后才能解析 base64String = base64String.replace("data:image/png;base64,",""); //在本地指定位置建立文件夹,path由控制台那边进行定义 String realPath = path+"/"+"echarts"; File dir=new File(realPath); if(!dir.exists()){ dir.mkdirs(); } String fileName=path+"\\"+"echarts"+"\\"+UUID.randomUUID().toString()+".png"; try { byte[] buffer = decoder.decodeBuffer(base64String); OutputStream os = new FileOutputStream(fileName); for(int i =0;i<buffer.length;++i){ if(buffer[i]<0){//调整异常数据 buffer[i]+=256; } } os.write(buffer); os.close(); } catch (IOException e) { throw new RuntimeException(); } return fileName; } /** * 读取图片在本地存储的位置 * @param imgFile * @throws Exception */ public String getImageStr(String imgFile) { InputStream in = null; byte[] data = null; try { in = new FileInputStream(imgFile); data = new byte[in.available()]; in.read(data); in.close(); } catch (IOException e) { e.printStackTrace(); } BASE64Encoder encoder = new BASE64Encoder(); return encoder.encode(data); } }
3、接下来就要介绍下在控制台怎么使用工具类实现导出word啦,详细细节看注释
static String MODELPATH = "/uploadFiles/…"; @RequestMapping(value = { "/downloadDoc" }, produces = "text/html;charset=UTF-8") public void downloadDoc(HttpServletRequest request, HttpServletResponse response) { //引入导出word的工具类 DocUtil docUtil = new DocUtil(); //引入处理图片的工具类,包含将base64编码解析为图片并保存本地,获取图片本地路径 ImageUtil imageUtil = new ImageUtil(); //建立map存储所要导出到word的各种数据和图像,不能使用自己项目封装的类型,例如PageData Map<String, Object> dataMap = new HashMap<String, Object>(); /* * 这一步,请求所需要导出到word的数据quotaList,把你们的数据处理放到这里就行了 */ //这一步,进行图片的处理,获取前台传过来的图片base64编码,在利用工具类解析图片保存到本地,然后利用工具类获取图片本地地址 String barBase64Info = request.getParameter("barBase64Info"); String path = "D:"; String image1 = ImageUtil.savePictoServer(barBase64Info, path); image1 = imageUtil.getImageStr(image1); //将以上处理的数据都存入dataMap 中 //以下都是进行word文件的处理,直接复制,然后细节按需修改就行了 request.setCharacterEncoding("utf-8"); File file = null; InputStream fin = null; OutputStream out = null; String filename = "文件名.doc"; //dataMap是上面处理完的数据,MODELPATH是模板文件的存储路径,"模板.xml"是相应的模板文件 file = docUtil.createDoc(dataMap, MODELPATH, "模板.xml", request); fin = new FileInputStream(file); response.setContentLength((int) file.length());//需要传递这个长度,不然下载文件后,打开提示内容有问题,如docx等 response.setCharacterEncoding("utf-8"); response.setContentType("application/msword"); response.setHeader("Content-disposition", "attachment;filename=" + new String(filename.getBytes("utf-8"), "iso8859-1")); out = response.getOutputStream(); byte[] buffer = new byte[1024]; // 缓冲区 int bytesToRead = -1; // 通过循环将读入的Word文件的内容输出到浏览器中 while ((bytesToRead = fin.read(buffer)) != -1) { out.write(buffer, 0, bytesToRead); } if (fin != null) fin.close(); if (out != null) out.close(); if (file != null) file.delete(); // 删除临时文件 }
注意:模板的list在后台构造的时候必须是实体类或者有属性类型的,如果是自己项目封装的类型,如在我的项目中有自己封装的PageData类型的,在模板的list是识别不出list里面的数据的。
各位看官看在本仙女这么辛苦分享的份上随手点个赞呗^_^!!!
相关推荐
81314797 2020-11-18
89314493 2020-11-03
81941231 2020-09-17
thisisid 2020-09-09
如狼 2020-08-15
82384399 2020-06-16
86384798 2020-05-12
80183053 2020-05-02
86384798 2020-04-26
86384798 2020-04-11
rionchen 2020-04-09
86384798 2020-04-07
86384798 2020-04-04
80183053 2020-03-07
87201943 2020-03-06
83961233 2020-02-26
87201943 2020-02-21