前面文章已經分享瞭如何建立導出word須要用到的xml/ftl模板了,接下來這裏要給你們分享的是如何用後臺製做導出word的代碼工具和controller實現。html
一、首先是工具類,沒有工具,談何實現呢?下面貼我這邊導出word的utils,你們能夠直接複製粘貼到大家項目就能夠引用了。java
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(); } } }
二、接下來是處理圖片的工具類,這裏導出word包含導出圖片到word,因此須要對圖片進行處理,是怎麼個原理呢,在這裏和你們簡單介紹下,具體在後續我會具體詳細另外寫一篇文章分享。
(1)圖片咱們能夠在前臺將要的圖片轉成base64編碼,而後提交給後臺接收
(2)後臺接收base64編碼後使用工具類將base64解碼成圖片而後保存到本地中
(3)在要導出word的時候讀取下本地存儲圖片的路徑而後把圖片導出來就好了。
工具類以下:同第一條同樣可直接複製到大家項目中使用。web
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); } }
三、接下來就要介紹下在控制檯怎麼使用工具類實現導出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裏面的數據的。segmentfault
各位看官看在本仙女這麼辛苦分享的份上隨手點個讚唄^_^!!!瀏覽器