大檔案資料分片上傳簡單示例
阿新 • • 發佈:2018-11-20
文章目錄
大檔案資料分片上傳簡單示例
1. HTML
<input type="file" name="file" id="file">
<input type="button" id="uploadSlice" value="檔案分片上傳">
2. JS
<script
src="http://code.jquery.com/jquery-3.3.1.js"
integrity="sha256-2Kok7MbOyxpgUVvAk/HJ2jigOSYS2auK4Pfzbm7uH60="
crossorigin="anonymous"></script>
<script>
$("#uploadSlice").on("click", function () {
uploadFile();
} );
//分成多少片
var sliceSize;
var timer;
function uploadFile() {
var file = $("#file")[0].files[0]; //檔案物件
if (file == undefined) {
alert("請先選中檔案");
return;
}
if (file.size > 1024 * 1024 * 1024 * 2) {
alert("檔案不能大於2GB");
return ;
}
var sliceLength = 1024 * 1024 * 100; //每片大小
sliceSize = Math.ceil(file.size / sliceLength);
for (var i = 1; i <= sliceSize; i++) {
var fileTmp;
//最後一片
if (i == sliceSize) {
fileTmp = file.slice(sliceLength * (i - 1), file.size + 1);
} else {
fileTmp = file.slice(sliceLength * (i - 1), sliceLength * i);
}
uploadSlice(fileTmp, file, i);
if (i == 1) {
uploadSchedule();
}
}
}
function uploadSlice(formData, file, index) {
var form = new FormData();
form.append("fileSize", file.size);
form.append("sliceSize", sliceSize);
form.append("index", index);
form.append("file", formData);
form.append("fileName", file.name);
console.log("準備上傳第[" + index + "]個檔案");
$.ajax({
url: 'uploadSlice',
data: form,
type: 'post',
async: true,
processData: false,
contentType: false,
success: function (data) {
console.log("code:" + data.code)
if (data.code == 200) {
console.log("上傳第[" + index + "]個檔案成功");
}
},
error: function (data) {
console.log(data.code + "上傳第[" + index + "]個檔案發生錯誤" + data.msg + ",錯誤原因:");
console.log(data);
}
});
}
function uploadSchedule() {
timer = setInterval(function () {
$.ajax({
url: 'uploadSchedule',
type: 'post',
success: function (data) {
if (data.data == null) {
console.log(data);
}
if (data.data != null) {
console.log(data.data);
}
if (data.code == 200) {
console.log("進入清除定時器");
window.clearInterval(timer);
}
},
error: function (data) {
console.log(data);
}
});
}, 1000);
}
</script>
3. Java
3.1 檔案屬性實體類
/**
* @program: service-center
* @description: 檔案Model,前端將檔案切片後將資料分片傳給後臺
* @author: Mr.superbeyone
* @create: 2018-11-14 09:20
**/
public class FileModel {
private int fileSize; //檔案大小
private int sliceSize; //切片數量
private String md5; //檔案md5值
private int index; //當前為第幾片
private String fileName; //檔名
private MultipartFile file; //檔案
//GET SET
}
3.2 統一返回結果定義
/**
* @program:
* @description:
* @author: Mr.superbeyone
* @create: 2018-10-18 16:37
**/
public class JsonResult<T> {
private Integer code;
private String msg;
private T data;
//Get
//Set
}
3.3 Controller
@RestController
public class FileUploadController {
@Autowired
FileUploadService fileUploadService;
/**
* 資料分片上傳
*
* @param fileModel
* @return
*/
@RequestMapping("/uploadSlice")
public JsonResult<Object> uploadSlice(FileModel fileModel) {
Object uploadSchedule = RequestHolder.getCurrentRequest().getSession().getAttribute("uploadSchedule");
if (uploadSchedule == null) {
RequestHolder.getCurrentRequest().getSession().setAttribute("uploadSchedule", new FileOperatorSchedule());
}
JsonResult<Object> jsonResult = fileUploadService.uploadFileSlice(fileModel);
return jsonResult;
}
/**
* 獲取上傳任務進度
*
* @return
*/
@RequestMapping("/uploadSchedule")
public JsonResult<FileOperatorSchedule> getUploadSchedule(HttpServletRequest request) {
JsonResult<FileOperatorSchedule> result = new JsonResult<>();
Object uploadSchedule = request.getSession().getAttribute("uploadSchedule");
FileOperatorSchedule fileOperatorSchedule = null;
if (uploadSchedule != null) {
fileOperatorSchedule = (FileOperatorSchedule) uploadSchedule;
if (fileOperatorSchedule.getFileSize() <= fileOperatorSchedule.getCompletedSize()) {
result.setCode(200);
result.setMsg("上傳任務完成");
RequestHolder.getCurrentRequest().getSession().removeAttribute("uploadSchedule");
} else {
result.setCode(600);
result.setMsg("上傳任務進行中");
}
} else {
result.setCode(900);
result.setMsg("資料準備中");
}
result.setData(fileOperatorSchedule);
return result;
}
}
3.4 Service實現類
/**
* @program: service-center
* @description:
* @author: Mr.superbeyone
* @create: 2018-10-19 12:54
**/
@Service
public class FileUploadServiceImpl implements FileUploadService {
/**
* 切片上傳檔案
*
* @param fileModel
* @return
*/
@Override
public JsonResult<Object> uploadFileSlice(FileModel fileModel) {
JsonResult<Object> result = new JsonResult<>();
//檔案儲存的父資料夾位置
File parentFolder = new File("D:\\data" + File.separator + fileModel.getFileName().substring(0, fileModel.getFileName().lastIndexOf(".")));
if (!parentFolder.exists()) {
parentFolder.mkdirs();
}
//檔案分片位置
File file = null;
if (fileModel.getSliceSize() == 1) {
file = new File(parentFolder, fileModel.getFileName());
} else {
file = new File(parentFolder, fileModel.getFileName() + "_" + fileModel.getIndex());
}
if (file.exists()) {
file.delete();
}
FileOperatorSchedule fileOperatorSchedule = (FileOperatorSchedule) RequestHolder.getCurrentRequest().getSession().getAttribute("uploadSchedule");
if (fileOperatorSchedule == null) {
fileOperatorSchedule = new FileOperatorSchedule();
}
fileOperatorSchedule.setFileSize(fileModel.getFileSize());
BufferedOutputStream bufferedOutputStream = null;
BufferedInputStream bufferedInputStream = null;
try {
//上傳檔案 1
// fileModel.getFile().transferTo(file);
//上傳檔案 2
bufferedOutputStream = new BufferedOutputStream(new FileOutputStream(file));
bufferedInputStream = new BufferedInputStream(fileModel.getFile().getInputStream());
int len = 0;
byte[] bytes = new byte[2048];
while ((len = bufferedInputStream.read(bytes)) != -1) {
bufferedOutputStream.write(bytes, 0, len);
}
//判斷所有分片是否上傳完成,完成則合併
File[] files = parentFolder.listFiles();
if (files.length == fileModel.getSliceSize()) { //上傳完成
if (fileModel.getSliceSize() > 1) {
File newFile = new File(parentFolder, fileModel.getFileName());
bufferedOutputStream = new BufferedOutputStream(new FileOutputStream(newFile, true));
for (int i = 1; i <= files.length; i++) {
bufferedInputStream = new BufferedInputStream(new FileInputStream(new File(parentFolder, fileModel.getFileName() + "_" + i)));
while ((len = bufferedInputStream.read(bytes)) != -1) {
bufferedOutputStream.write(bytes, 0, len);
}
}
bufferedInputStream.close();
bufferedOutputStream.close();
}
for (int i = 1; i <= parentFolder.listFiles().length; i++) {
File splitFile = new File(parentFolder, fileModel.getFileName() + "_" + i);
if (splitFile.exists()) {
if (splitFile.delete()) {
logger.debug(splitFile.getName() + "刪除成功");
} else {
logger.error( splitFile.getName() + "刪除失敗");
}
}
}
result.setCode(200);
result.setMsg("上傳成功");
result.setData(fileModel.getFileName());
} else {
result.setCode(800);
result.setMsg("上傳失敗");
}
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
if (bufferedInputStream != null) {
bufferedInputStream.close();
}
if (bufferedOutputStream != null) {
bufferedOutputStream.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
return result;
}
}