后端springmvc,前端html5的FormData实现文件断点上传
前言
最近项目中有使用到文件断点上传,得空便总结总结,顺便记录一下,毕竟“好记性不如烂笔头”。
后端代码:
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; } }
前端代码:
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.html
阿杰de博客,qq群:112465270