1.准備工作
1.1.添加上傳必要jar包
<dependency> <groupId>commons-io</groupId> <artifactId>commons-io</artifactId> <version>2.4</version> </dependency> <dependency> <groupId>commons-fileupload</groupId> <artifactId>commons-fileupload</artifactId> <version>1.3.1</version> </dependency>
1.2.springmvc xml配置
1 <!-- SpringMVC上傳文件時,需要配置MultipartResolver處理器 --> 2 <bean id="multipartResolver" 3 class="org.springframework.web.multipart.commons.CommonsMultipartResolver"> 4 <property name="defaultEncoding" value="UTF-8" /> 5 <!-- 指定所上傳文件的總大小,單位字節。注意maxUploadSize屬性的限制不是針對單個文件,而是所有文件的容量之和 --> 6 <property name="maxUploadSize" value="10240000" /> 7 </bean>
2.前端頁面代碼
注意不論是上傳 圖片還是 doc文檔等,前端寫法都一樣,只是后端解析工具類不一樣而已

1 <%@ page contentType="text/html;charset=UTF-8" language="java" %> 2 <html> 3 <head> 4 <title>ajax請求上傳文件</title> 5 <script type="text/javascript" src="/static/js/jquery.min.js"></script> 6 </head> 7 <body> 8 <%--頁面按鈕--%> 9 <button id="addImport">導入</button> 10 <%--隱藏的文件輸入框--%> 11 <input id="FileUpload" name="file" type="file" onchange="uploadWord()" style="display: none"/> 12 </body> 13 <script type="text/javascript"> 14 /** 15 * 導入word文檔入口 16 */ 17 $('#addImport').click(function () { 18 openFileDialogue(); 19 }); 20 /** 21 * 打開上傳文件對話框 22 */ 23 function openFileDialogue() { 24 var f = document.getElementById('FileUpload'); 25 f.click(); 26 } 27 28 /** 29 * 文件上傳 前檢查與確認 30 */ 31 var msg; 32 function uploadWord() { 33 var fileObj = document.getElementById("FileUpload").files[0]; // js 獲取文件對象 34 var fileObjName = $("#FileUpload").val(); 35 if (typeof (fileObj) == "undefined" || fileObj.size <= 0) { 36 alert("請選擇要導入的文檔?"); 37 return; 38 } 39 //判斷是否為 doc 或 docx 文件 40 var fileName = getFileName(fileObjName); 41 var fileSuffix = getFileSuffix(fileObjName); 42 if (fileSuffix != 'doc' && fileSuffix != 'docx') { 43 alert("----請選擇正確的文件格式---------"); 44 return; 45 } 46 //確認是否上傳(略) 47 //執行上傳 48 uploadWordDo(fileObj, fileName); 49 50 } 51 52 /** 53 * 發送ajax請求 執行上傳 54 */ 55 function uploadWordDo(fileObj) { 56 var formFile = new FormData(); 57 formFile.append("file", fileObj); //加入文件對象 58 formFile.append("basePath", ""); //加入文件對象 59 var data = formFile; 60 $.ajax({ 61 url: "/upload/do", 62 data: data, 63 type: "Post", 64 dataType: "json", 65 async: true, 66 cache: false, 67 processData: false,//用於對data參數進行序列化處理 這里必須false 68 contentType: false, //必須 69 success: function (result) { 70 //成功提示 71 var code = result.code; 72 if (code == '0000') { 73 alert("--上傳成功---"); 74 } else { 75 alert("--失敗---"); 76 } 77 } 78 }); 79 } 80 /** 81 * 獲取文件名 82 * @param file 83 * @returns {*} 84 */ 85 function getFileName(file) { 86 var arr = file.split('\\'); 87 return arr[arr.length - 1]; 88 } 89 90 /** 91 * 獲取后綴 92 * @param file 93 * @returns {string} 94 */ 95 function getFileSuffix(file) { 96 var point = file.lastIndexOf("."); 97 var type = file.substr(point + 1); 98 return type; 99 } 100 101 </script> 102 </html>
3.后端處理
后端controller主要有兩個方法,一個是獲取上傳頁面的方法,另一個是處理上傳的方法

1 package com.linrain.jcs.controller.bbsNews; 2 3 import com.alibaba.fastjson.JSONObject; 4 import com.linrain.jcs.constant.CommonConstant; 5 import com.linrain.jcs.tool.DateUtil; 6 import com.linrain.jcs.tool.downPOI.baseDown.PoiUtil; 7 import org.springframework.stereotype.Controller; 8 import org.springframework.web.bind.annotation.RequestMapping; 9 import org.springframework.web.bind.annotation.RequestMethod; 10 import org.springframework.web.bind.annotation.RequestParam; 11 import org.springframework.web.bind.annotation.ResponseBody; 12 import org.springframework.web.multipart.MultipartFile; 13 14 import javax.servlet.http.HttpServletRequest; 15 import java.io.InputStream; 16 17 /** 18 * 文件上傳 19 * Created by 姿勢帝 on 2018/7/20. 20 * WX: 851298348 21 */ 22 @Controller 23 @RequestMapping(value = "/upload") 24 public class UploadController { 25 26 /** 27 * 文件上傳頁面 28 * 29 * @return 30 */ 31 @RequestMapping(value = "/page") 32 public String page() { 33 34 return "bbsNews/upload"; 35 } 36 37 /** 38 * 上傳doc 或 docx 39 * 40 * @param file 41 * @return 42 */ 43 @RequestMapping(value = "/do", method = RequestMethod.POST) 44 @ResponseBody 45 public Object doUploadFile(@RequestParam("file") MultipartFile file, HttpServletRequest request, String basePath) { 46 JSONObject jsonObject = new JSONObject(); 47 if (!file.isEmpty()) { 48 try { 49 InputStream inputStream = file.getInputStream(); 50 String originalFilename = file.getOriginalFilename(); 51 String fileName = DateUtil.getTimeString() + originalFilename; 52 //文件處理工具類(以后什么文件,這里就調用什么處理工具就可以了,這里是將上傳的doc文件轉變為html文件) 53 String con = PoiUtil.getHtml(inputStream, fileName); 54 jsonObject.put("content", con); 55 jsonObject.put("success", true); 56 jsonObject.put("code", CommonConstant.CODE_SUCCESS); 57 return jsonObject; 58 } catch (Exception e) { 59 e.printStackTrace(); 60 61 } 62 } 63 jsonObject.put("success", false); 64 jsonObject.put("code", CommonConstant.CODE_IMPORT_FALSE); 65 jsonObject.put("msg", "文檔導入失敗!"); 66 return jsonObject; 67 } 68 }
4.工具處理類
該工具類中主要處理 將doc或docx轉變為--html文件

1 package com.linrain.jcs.tool.downPOI.baseDown; 2 3 /** 4 * Created by Administrator on 2018/11/29. 5 */ 6 7 import com.linrain.jcs.tool.ConfigUtil; 8 import org.apache.poi.hwpf.HWPFDocument; 9 import org.apache.poi.hwpf.converter.PicturesManager; 10 import org.apache.poi.hwpf.converter.WordToHtmlConverter; 11 import org.apache.poi.hwpf.usermodel.PictureType; 12 import org.apache.poi.xwpf.converter.core.BasicURIResolver; 13 import org.apache.poi.xwpf.converter.core.FileImageExtractor; 14 import org.apache.poi.xwpf.converter.xhtml.XHTMLConverter; 15 import org.apache.poi.xwpf.converter.xhtml.XHTMLOptions; 16 import org.apache.poi.xwpf.usermodel.XWPFDocument; 17 import org.slf4j.Logger; 18 import org.slf4j.LoggerFactory; 19 import org.w3c.dom.Document; 20 21 import javax.xml.parsers.DocumentBuilderFactory; 22 import javax.xml.transform.OutputKeys; 23 import javax.xml.transform.Transformer; 24 import javax.xml.transform.TransformerFactory; 25 import javax.xml.transform.dom.DOMSource; 26 import javax.xml.transform.stream.StreamResult; 27 import java.io.*; 28 import java.util.UUID; 29 30 /** 31 * Created by 姿勢帝 on 2018/11/299. 32 * 使用poi將word轉為html文件,並從文件中讀取內容 33 * wx:851298348 34 */ 35 public class PoiUtil { 36 private static final Logger log = LoggerFactory.getLogger(PoiUtil.class); 37 // 在html中圖片保存的相對路徑 static/images/upload 38 // private static String imagePath = "\\static\\images\\upload\\"; 39 private static String imagePath = ConfigUtil.getTempImagePath(); 40 private static String imagePathStr; //圖片絕對地址 41 public static String rootPath;//項目跟路徑 42 public static Long tempTime;//項目跟路徑 43 44 /** 45 * 初始換圖片地址 46 */ 47 static { 48 RegexAnswerUtil regexAnswerUtil = new RegexAnswerUtil(); 49 rootPath = regexAnswerUtil.getRootPath(); 50 imagePathStr = rootPath + imagePath; 51 log.info(" imagePathStr = " + imagePathStr); 52 tempTime = ConfigUtil.getTempTime(); 53 } 54 55 /** 56 * 更具文件名稱判斷是否超時 57 */ 58 public static boolean haveOvertime(String fileName) { 59 boolean flag = false; 60 if (fileName == null || fileName.length() < 14) { 61 return flag; 62 } 63 try { 64 String substring = fileName.substring(0, 13); 65 Long fileTime = Long.valueOf(substring); 66 Long nowTime = System.currentTimeMillis(); 67 long l = nowTime - fileTime; 68 // long time = 2 * 60 * 60 * 1000; // 2個小時 69 //long time = 2 * 60 * 1000; // 2 分鍾 70 if (l > tempTime) { 71 flag = true; 72 } 73 } catch (Exception e) { 74 e.printStackTrace(); 75 } 76 return flag; 77 } 78 79 /** 80 * 刪除文件 81 */ 82 public static void del() { 83 File file = new File(imagePathStr); 84 delete(file); 85 } 86 87 /** 88 * 根據地址刪除文件 89 * 90 * @param path 91 */ 92 public static void deletePic(String path) { 93 File file = new File(path); 94 boolean delete = file.delete(); 95 log.info(" delete=" + delete + "path=" + path); 96 } 97 98 public static String getTimeUUID() { 99 String s = UUID.randomUUID().toString(); 100 s = s.substring(0, 4); 101 return System.currentTimeMillis() + "-word" + s; 102 } 103 104 /** 105 * 根據文件遞歸刪除 106 * 107 * @param file 108 */ 109 public static void delete(File file) { 110 if (!file.exists()) return; 111 if (file.isFile() || file.list() == null) { 112 String path = file.getPath(); 113 String name = file.getName(); 114 if (haveOvertime(name)) { 115 boolean delete = file.delete(); 116 log.info("delete=" + delete + " path=" + path); 117 } else { 118 log.info("該文不符合刪除條件 path=" + path); 119 } 120 121 } else { 122 File[] files = file.listFiles(); 123 for (File a : files) { 124 delete(a); 125 } 126 boolean delete = file.delete(); 127 log.info("刪除文件夾 delete =" + delete + " path=" + file.getPath()); 128 } 129 } 130 131 /** 132 * @param inputStream word文件的File對象 133 * @param sourceFileName word文件名 134 * @return 轉成的html字符串 135 */ 136 public static String getHtml(InputStream inputStream, String sourceFileName) throws Exception { 137 String content; 138 // 判斷word文檔類型,使用不同方法進行轉換 139 if (sourceFileName.endsWith(".doc")) { 140 content = docToHtml(inputStream, sourceFileName); 141 } else if (sourceFileName.endsWith(".docx")) { 142 content = docxToHtml(inputStream, sourceFileName); 143 } else { 144 return "文件類型錯誤"; 145 } 146 // 利用正則表達式過濾無用標簽和屬性 147 // content = RegexAnswerUtil.clear(content); 148 return content; 149 } 150 151 152 /** 153 * 將doc文件轉變為html 154 * 155 * @param fileInputStream 156 * @param sourceFileName 157 * @return 158 * @throws Exception 159 */ 160 public static String docToHtml(InputStream fileInputStream, String sourceFileName) throws Exception { 161 String targetFileName = imagePathStr + sourceFileName.substring(0, sourceFileName.lastIndexOf(".")) + ".html"; 162 HWPFDocument wordDocument = new HWPFDocument(fileInputStream); 163 Document document = DocumentBuilderFactory.newInstance().newDocumentBuilder().newDocument(); 164 WordToHtmlConverter wordToHtmlConverter = new WordToHtmlConverter(document); 165 // 保存圖片,並返回圖片的相對路徑 166 wordToHtmlConverter.setPicturesManager(new PicturesManager() { 167 @Override 168 public String savePicture(byte[] content, PictureType pictureType, String name, float width, float height) { 169 name = getTimeUUID() + name; 170 try (FileOutputStream out = new FileOutputStream(new File(imagePathStr + name))) { 171 out.write(content); 172 } catch (Exception e) { 173 e.printStackTrace(); 174 } 175 return imagePath + "\\" + name; 176 } 177 }); 178 179 /*wordToHtmlConverter.setPicturesManager((content, pictureType, name, width, height) -> { 180 // name = DateUtil.getTimeString() + name; 181 name = getTimeUUID() + name; 182 try (FileOutputStream out = new FileOutputStream(new File(imagePathStr + name))) { 183 out.write(content); 184 } catch (Exception e) { 185 e.printStackTrace(); 186 } 187 return imagePath + "\\" + name; 188 });*/ 189 wordToHtmlConverter.processDocument(wordDocument); 190 Document htmlDocument = wordToHtmlConverter.getDocument(); 191 DOMSource domSource = new DOMSource(htmlDocument); 192 StreamResult streamResult = new StreamResult(new File(targetFileName)); 193 TransformerFactory tf = TransformerFactory.newInstance(); 194 Transformer serializer = tf.newTransformer(); 195 serializer.setOutputProperty(OutputKeys.ENCODING, "utf-8"); 196 serializer.setOutputProperty(OutputKeys.INDENT, "yes"); 197 serializer.setOutputProperty(OutputKeys.METHOD, "html"); 198 serializer.transform(domSource, streamResult); 199 String content = splitContext(targetFileName); 200 // 刪除生成的html文件 201 File file = new File(targetFileName); 202 // file.delete(); 203 System.out.println("content= " + content); 204 return content; 205 } 206 207 /** 208 * docx轉換為html 209 * 210 * @param inputStream 211 * @param sourceFileName 212 * @return 213 * @throws Exception 214 */ 215 public static String docxToHtml(InputStream inputStream, String sourceFileName) throws Exception { 216 String targetFileName = imagePathStr + sourceFileName.substring(0, sourceFileName.lastIndexOf(".")) + ".html"; 217 File target = new File(targetFileName); 218 target.getParentFile().mkdirs(); 219 OutputStreamWriter outputStreamWriter = null; 220 try { 221 XWPFDocument document = new XWPFDocument(inputStream); 222 XHTMLOptions options = XHTMLOptions.create(); 223 // 存放圖片的文件夾 224 options.setExtractor(new FileImageExtractor(new File(imagePathStr))); 225 // html中圖片的路徑 226 options.URIResolver(new BasicURIResolver(imagePath)); 227 outputStreamWriter = new OutputStreamWriter(new FileOutputStream(target), "utf-8"); 228 XHTMLConverter xhtmlConverter = (XHTMLConverter) XHTMLConverter.getInstance(); 229 xhtmlConverter.convert(document, outputStreamWriter, options); 230 } finally { 231 if (outputStreamWriter != null) { 232 outputStreamWriter.close(); 233 } 234 } 235 String content = splitContext(targetFileName); 236 // 刪除生成的html文件 237 File file = new File(targetFileName); 238 file.delete(); 239 // System.out.println(" content docx= " + content); 240 return content; 241 } 242 243 /** 244 * 讀取轉換得到的html文件,並過濾多余空行 245 */ 246 public static String splitContext(String filePath) { 247 File file = new File(filePath); 248 BufferedReader reader = null; 249 try { 250 InputStreamReader isr = new InputStreamReader(new FileInputStream(file), "UTF-8"); 251 reader = new BufferedReader(isr); 252 StringBuilder sb = new StringBuilder(); 253 String tempString = null; 254 // 一次讀入一行,直到讀入null為文件結束 255 while ((tempString = reader.readLine()) != null) { 256 sb.append(tempString); 257 if (!"".equals(tempString)) { 258 sb.append("\n"); 259 } 260 } 261 reader.close(); 262 String content = sb.toString().replaceAll("\\n+", "\n"); 263 return content; 264 } catch (IOException e) { 265 e.printStackTrace(); 266 } finally { 267 if (reader != null) { 268 try { 269 reader.close(); 270 } catch (IOException e1) { 271 } 272 } 273 } 274 return ""; 275 } 276 }
5.測試
5.1.頁面效果
5.2.點擊導入按鈕
5.3.導入成功提示
注意:本文中主要講解上傳流程和邏輯,實際生產中需要根據產品要求給出友好提示,如文件類型限制,上傳前提醒用戶使用上傳該文件等友好提示
完美!