博客地址:https://ainyi.com/76html
平常,工做前端
在這裏總結一下上傳吧(是之前作過的練習,就彙總到我的博客吧)java
java ssm 框架實現文件上傳
實現:單文件上傳、多文件上傳(單選和多選),而且用 ajax 異步刷新,在當前界面顯示上傳的文件web
首先 springmvc 的配置文件要配置上傳文件解析器:ajax
<!-- 配置文件解析器 --> <bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver" p:defaultEncoding="utf-8"> <property name="uploadTempDir" value="/temp"></property> <property name="maxUploadSize"> <value>209715200</value><!-- 200MB --> </property> <property name="maxInMemorySize"> <value>4096</value><!-- 4KB大小讀寫 --> </property> </bean>
其次在 pom.xml 中要配置上傳文件的依賴spring
<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> <dependency> <groupId>org.apache.commons</groupId> <artifactId>commons-lang3</artifactId> <version>3.3.2</version> </dependency>
單文件上傳apache
/** * 單文件上傳 * @param file * @param request * @return * @throws IllegalStateException * @throws IOException * @throws JSONException */ public static String simUpload(MultipartFile file, HttpServletRequest request) throws IllegalStateException, IOException, JSONException{ if(!file.isEmpty()){ String path = request.getSession().getServletContext().getRealPath("/upload"); //定義文件 File parent = new File(path); if(!parent.exists()) parent.mkdirs(); HashMap<String, Object> map = new HashMap<String,Object>(); String oldName = file.getOriginalFilename(); long size = file.getSize(); //使用TmFileUtil文件上傳工具獲取文件的各類信息 //優化文件大小 String sizeString = TmFileUtil.countFileSize(size); //獲取文件後綴名 String ext = TmFileUtil.getExtNoPoint(oldName); //隨機重命名,10位時間字符串 String newFileName = TmFileUtil.generateFileName(oldName, 10, "yyyyMMddHHmmss"); String url = "upload/"+newFileName; //文件傳輸,parent文件 file.transferTo(new File(parent, newFileName)); map.put("oldname",oldName);//文件原名稱 map.put("ext",ext); map.put("size",sizeString); map.put("name",newFileName);//文件新名稱 map.put("url",url); //以json方式輸出到頁面 return JSONUtil.serialize(map); }else{ return null; } }
多文件上傳(整合了==單選文件==和==多選文件==的兩種)json
/** * 多文件上傳 * @param files * @param request * @return * @throws IllegalStateException * @throws IOException * @throws JSONException */ public static List<HashMap<String, Object>> mutlUpload(MultipartFile[] files, HttpServletRequest request) throws IllegalStateException, IOException, JSONException{ if(files.length > 0){ String path = request.getSession().getServletContext().getRealPath("/upload"); //定義文件 File parent = new File(path); if(!parent.exists()) parent.mkdirs(); //建立這個集合保存全部文件的信息 List<HashMap<String, Object>> listMap = new ArrayList<HashMap<String, Object>>(); //循環屢次上傳多個文件 for (MultipartFile file : files) { //建立map對象保存每個文件的信息 HashMap<String, Object> map = new HashMap<String,Object>(); String oldName = file.getOriginalFilename(); long size = file.getSize(); //使用TmFileUtil文件上傳工具獲取文件的各類信息 //優化文件大小 String sizeString = TmFileUtil.countFileSize(size); //獲取文件後綴名 String ext = TmFileUtil.getExtNoPoint(oldName); //隨機重命名,10位時間字符串 String newFileName = TmFileUtil.generateFileName(oldName, 10, "yyyyMMddHHmmss"); String url = "upload/"+newFileName; //文件傳輸,parent文件 file.transferTo(new File(parent, newFileName)); map.put("oldname",oldName);//文件原名稱 map.put("ext",ext); map.put("size",sizeString); map.put("name",newFileName);//文件新名稱 map.put("url",url); listMap.add(map); } //以json方式輸出到頁面 return listMap; }else{ return null; } }
前端代碼:
文件多選,實際上在後端
<input type="file" name="fileupmulti" accept="image/jpeg,image/png" onchange="mutiFiles(this)" multiple/>
多加了一個 multiple 屬性數組
onchange 事件代碼
// 單文件上傳 function uploadFile(obj){ // 建立一個 FormData 對象,用一些鍵值對來模擬一系列表單控件 // 即把 form 中全部表單元素的 name 與 value 組裝成一個 queryString let form = new FormData(); let fileObj = obj.files[0]; form.append('doc',fileObj); // ajax 代碼... } // 多文件上傳(多選) function mutiFiles(obj){ let form = new FormData(); let fileObj = obj.files; let length = fileObj.length; // 將 fileObj 轉換成數組 // let filese = Array.from(fileObj); for(let i = 0; i < length; i++){ form.append('doc', fileObj[i]); } // ajax 代碼... } // 多文件上傳(單選:一個一個選擇文件,最後點擊提交按鈕觸發的方法) function multipartone(){ let file1 = $('.fileupon11').get(0).files[0]; let file2 = $('.fileupon12').get(0).files[0]; let file3 = $('.fileupon13').get(0).files[0]; //若是都是空,則直接退出 isEmpty(file1) && isEmpty(file2) && isEmpty(file3) return; let form = new FormData(); //用同一個名字,注入到controller層的參數數組 form.append('doc', file1); form.append('doc', file2); form.append('doc', file3); // ajax 代碼... }
要想在當前界面顯示上傳的文件,而不跳轉,就利用 ajax 異步請求
不過須要注意的是,我這裏使用 FormData() 儲存文件對象, ajax 要配上這幾個參數纔可實現文件上傳:
$.ajax({ type: "post", data: form, // FormData()對象 url: basePath+"/upload/mutl", contentType: false, // 必須false纔會自動加上正確的Content-Type processData: false, // 必須false纔會避開 jQuery 對 formdata 的默認處理, XMLHttpRequest會對 formdata 進行正確的處理 success: function(data){ // TODO } })
controller 層調用
package com.krry.controller; import java.io.IOException; import java.util.HashMap; import java.util.List; import javax.servlet.http.HttpServletRequest; import org.apache.struts2.json.JSONException; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.ResponseBody; import org.springframework.web.multipart.MultipartFile; import com.krry.util.UploadUtil; /** * 文件上傳類 * KrryUploadController * @author krry * @version 1.0.0 * */ @Controller @RequestMapping("/upload") public class KrryUploadController { /** * 單文件上傳 * @param file * @param request * @return * @throws IllegalStateException * @throws IOException * @throws JSONException */ @ResponseBody @RequestMapping(value = "/file") public String krryupload(@RequestParam("doc") MultipartFile file, HttpServletRequest request) throws IllegalStateException, IOException, JSONException{ //調用工具類完成上傳,返回相關數據到頁面 return UploadUtil.simUpload(file, request); } /** * 多文件上傳 * @param file * @param request * @return * @throws IllegalStateException * @throws IOException * @throws JSONException */ // 這裏的MultipartFile[] file表示前端頁面上傳過來的多個文件,file對應頁面中多個file類型的input標籤的name,但框架只會將一個文件封裝進一個MultipartFile對象, // 並不會將多個文件封裝進一個MultipartFile[]數組,直接使用會報[Lorg.springframework.web.multipart.MultipartFile;.<init>()錯誤, // 因此須要用@RequestParam校訂參數(參數名與MultipartFile對象名一致),固然也能夠這麼寫:@RequestParam("file") MultipartFile[] files。 @ResponseBody @RequestMapping(value = "/mutl") public List<HashMap<String, Object>> krryuploadMutl(@RequestParam("doc") MultipartFile[] file, HttpServletRequest request) throws IllegalStateException, IOException, JSONException{ //調用工具類完成上傳,返回相關數據到頁面 return UploadUtil.mutlUpload(file, request); } }
要顯示上傳進度條,我這裏採用原生 ajax 方法
function uploadFile(obj) { // ... // 一些獲取上傳對象的相關代碼 // 建立一個 ajax 對象 var xhr = new XMLHttpRequest(); // 規定請求的類型、URL 以及是否異步處理請求。true爲異步 // 請求是異步的。由於要實時獲取到上傳的進度,則請求需是異步的,若是是同步的話,會直到請求完成才能獲取到響應 xhr.open("post", basePath+"/upload/file", true); // 上傳成功進入的回調函數 xhr.onreadystatechange = function(){ if(xhr.readyState==4 && xhr.status==200){ // 狀態 4 和 200 表明和服務器端交互成功 // 獲取上傳成功的返回數據 var data = xhr.responseText.trim(); jdata = eval("("+data+")"); krry_uploadsuccess(jdata); } }; // 監聽文件上傳的進度 xhr.upload.addEventListener("progress", progressFunction, false); // 發送http請求:將請求發送到服務器,與後臺交互 xhr.send(form); } // 上傳進度的回調函數 function progressFunction(event) { let prograssbarDom = document.getElementById("prograssbar"); let fileRea = document.getElementById("fileRea"); if (prograssbarDom && event.lengthComputable) { let percent = event.loaded / event.total; //文件上傳進度百分比 let p = Math.floor(percent*100); prograssbarDom.style.width = p+"%"; fileRea.innerHTML = p+"%"; } }
附上優化文件大小的代碼:
/** * 將文件的字節數轉換成文件的大小 * com.krry.uitl * 方法名:format * @author krry * @param size * @return String * @exception * @since 1.0.0 */ public static String format(long size){ float fsize = size; String fileSizeString; if (fsize < 1024) { fileSizeString = String.format("%.2f", fsize) + "B"; //2f表示保留兩位小數 } else if (fsize < 1048576) { fileSizeString = String.format("%.2f", fsize/1024) + "KB"; } else if (fsize < 1073741824) { fileSizeString = String.format("%.2f", fsize/1024/1024) + "MB"; } else if (fsize < 1024 * 1024 * 1024) { fileSizeString = String.format("%.2f", fsize/1024/1024/1024) + "GB"; } else { fileSizeString = "0B"; } return fileSizeString; }
博客地址:https://ainyi.com/76