前言javascript
最近項目中有使用到文件斷點上傳,得空便總結總結,順便記錄一下,畢竟「好記性不如爛筆頭」。html
後端代碼:前端
package com.test.controller; import java.io.BufferedOutputStream; import java.io.File; import java.io.FileOutputStream; import java.util.UUID; import org.apache.commons.io.FileUtils; import org.apache.commons.io.FilenameUtils; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.ResponseBody; import org.springframework.web.multipart.MultipartFile; @Controller public class UploadController { @ResponseBody // 返回rest json @RequestMapping(value = {"/rest/saveUploadFileAsChunk"}, method = RequestMethod.POST, produces = "application/json") public File saveUploadFileAsChunk(@RequestParam(required = false) MultipartFile file, @RequestParam(required = true) Integer chunk, // 分割塊數 @RequestParam(required = true) Integer chunks, // 總分割數 @RequestParam(required = true) String tempFileName //臨時文件名 必須帶後綴名 ) throws Exception{ if(null != file){ // 保存臨時文件 String chunkName = tempFileName; if (chunk != null) { chunkName = chunk + "_" + tempFileName; } File savedFile = new File("普通存放文件的路徑", chunkName); if (!savedFile.getParentFile().exists()) savedFile.getParentFile().mkdirs(); file.transferTo(savedFile); //將MultipartFile轉存到file對象 } //若是到最後一個分割塊,則作合併處理 if (chunk != null && chunk + 1 == chunks) { String newFileName = UUID.randomUUID().toString().replace("-", "").concat(".").concat(FilenameUtils.getExtension(tempFileName)); BufferedOutputStream outputStream = new BufferedOutputStream(new FileOutputStream(new File("普通存放文件的路徑", newFileName))); // 遍歷文件合併 chunks,循環將文件寫入新的文件中,而且刪除以前的臨時文件 for (int i = 0; i < chunks; i++) { File tempFile = new File("普通存放文件的路徑", i + "_" + tempFileName); byte[] bytes = FileUtils.readFileToByteArray(tempFile); //將file對象解析城byte數組 outputStream.write(bytes); outputStream.flush(); tempFile.delete(); } outputStream.flush(); outputStream.close(); File reallyFile = new File("普通存放文件的路徑", newFileName); //reallyFile即最後合併的文件 return reallyFile; } return null; } }
前端代碼: java
var setsize = 10 * 1024; //1024字節 = 1KB * 10 即每次10k /** *參數filepath就是本地文件路徑,主要就是用於放在localStorage中肯定惟一性 file : js的Blob對象 */ function uplaod(filepath,file){ var filesize = file.size; var filecount = filesize/setsize; //計算出能夠分紅幾塊 var i = localStorage.getItem(filepath); i = (i!=null && i!="")?parseInt(i):0; if(i < filecount){ //新建一個FormData對象 var formData = new FormData(); //++++++++++ var blobfile; if((filesize - i * setsize) > setsize){ blobfile = file.slice(i*setsize,(i+1)*setsize); }else{ //表明是最後一此了 blobfile = file.slice(i*setsize,filesize); } formData.append('chunk', i); //++++++++++當前文件塊 formData.append('chunks', Math.ceil(filecount)); //++++++++++ 總塊數 formData.append("tempFileName",fileName); //臨時文件名 帶uuid的 formData.append('file', blobfile); if(i < filecount){ $.ajax({ url: PATROL_CONSTANTS.SRV_URL+"/rest/saveUploadFileAsChunk", type: 'POST', data: formData, processData: false, contentType: false, success: function (responseStr) { localStorage.setItem(filepath,i+1); var rs = filecount <= 0 ? "0%" : (Math.round((i+1) / Math.ceil(filecount) * 10000) / 100.00 + "%"); console.log("進度百分比:"+rs); uploadFile(filepath,file); //遞歸調用 }, error: function (responseStr) { console.log("上傳失敗,重複嘗試!"); console.log(responseStr); uploadFile(filepath,file); } }); }else{ //上傳完成後,則將對應的localStorage移除掉 localStorage.removeItem(filepath); } }
轉發請標註原文地址:http://www.cnblogs.com/dinglinjie/p/7458901.htmlweb
阿杰de博客,qq羣:112465270ajax