前言
最近項目中有使用到文件斷點上傳,得空便總結總結,順便記錄一下,畢竟“好記性不如爛筆頭”。
后端代碼:
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
