思路:
1.前端进行文件分割,然后上传文件片段;
2.后端进行文件接收,和合并操作。
前端代码:
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<link th:replace="fragments/layout2::header">
<!--引入JQ-->
<script th:src="@{/static/Inspinia/js/jquery-3.3.1/jquery.min.js}"></script>
<meta charset="UTF-8">
<title></title>
</head>
<body>
<form>
<input type="file" id="files">
<input type="button" value="上传" onclick="uploadFile()" id = "uploadButton">
</form>
<div th:replace="fragments/layout2::js"></div>
<script src="../../static/md5/md5.js"></script>
<script>
// i :分片文件的标号
var i = -1;
//succeed :已上传成功的分片数量
var succeed = 0;
//action:upload方法要执行的操作(false时去检验分片是否上传过(默认); true时进行上传文件操作)
var action = false;
//验证大文件整体是否上传过的方法,参数为单个文件对象
function isUpload(file) {
//构造一个表单
var form = new FormData();
//整体文件的md5
var fileWholeMd5 = hex_md5(file);
form.append("fileMd5",fileWholeMd5);
form.append("originalFileName",file.name);
form.append("fileSize",file.size);
//发ajax到后台验证整体文件是否上传过
$.ajax({
url: "/upload/fileRecordWhole/isUpload",
type: "POST",
data: form,
async: true, //异步
processData: false, //很重要,告诉jquery不要对form进行处理
contentType: false, //很重要,指定为false才能形成正确的Content-Type
success: function(result){
console.log(result);
if(result != null){
var data = result.data;
if(data != undefined && data.status == 0){
//如果返回数据的状态为0(未完成),则上传各个分片文件
upload(file,data.id,fileWholeMd5,data.fileType,data.filePath,data.fileServerSn);
}else if(data != undefined && data.status == 1){
//如果返回数据的状态为1(已完成且存在),则提示上传成功;是否在此时创建任务需要后续确认
alert("上传成功");
}
}
},error: function(XMLHttpRequest, textStatus, errorThrown) {
alert("服务器出错!");
}
})
}
/**
* 分片并递归上传分片文件的方法
* @param file 大文件对象
* @param fileWholeId 整体文件记录 的id
* @param fileWholeMd5 整体文件的Md5
* @param fileType 文件类型(后缀)
* @param 整体文件的存储路径
* @param fileServerSn 整体文件存储的文件服务器序列号
*/
function upload(file, fileWholeId, fileWholeMd5,fileType,filePath,fileServerSn) {
var size = file.size; //总大小
var shardSize = 30 * 1024 * 1024, //以5MB为一个分片
shardCount = Math.ceil(size / shardSize); //总片数(取整)
if(i < shardCount){
//如果当前要执行校验分片是否存在的操作
if(!action){
i ++;
}
}else{
i = -1;
}
//计算每一片的起始位置和结束位置
var start = i * shardSize,
end = Math.min(size , start + shardSize);
//创建一个表单对象
var form = new FormData();
//分片文件名:整体文件的MD5 + (i+1)
var fileName = fileWholeMd5 + (i+1);
form.append("fileName",fileName);
form.append("fileWholeId",fileWholeId);
form.append("fileServerSn",fileServerSn);
//获取分片文件的存储路径
var wholeFileName = fileWholeMd5 + "." + fileType;
var shardFilePath = filePath.replace(wholeFileName,fileName);
form.append("filePath",shardFilePath);
//按大小切割文件段
var data = file.slice(start, end);
//这里使用文件阅读器,等待加载;可以防止递归调用被系统判定为死循环报错
var r = new FileReader();
r.readAsBinaryString(data);
$(r).on('load',function (e) {
var md5 = hex_md5(data);
form.append("fileMd5",md5);
if(!action){
//要执行的操作:校验分片是否上传
form.append("action","check");
}else{
//要执行的操作:上传分片文件
form.append("action","upload");
//分片文件对象
form.append("file",data);
}
$.ajax({
url: "/upload/fileRecordTem/upload",
type: "POST",
data: form,
async: false, //异步
processData: false, //很重要,告诉jquery不要对form进行处理
contentType: false, //很重要,指定为false才能形成正确的Content-Type
success: function(result){
// console.log(result);
var data = result.data;
// console.log(data);
if(data != undefined){
console.log("进来了");
if(data){
//分片文件已存在或上传成功,则进行下一片文件的操作
action = false;
succeed ++;
if(succeed < shardCount){
//递归调用
// console.log("递归调用")
upload(file,fileWholeId,fileWholeMd5,fileType,filePath,fileServerSn);
}else{
//进行文件合并
// console.log("合并文件")
mergeFile(fileWholeId,filePath,fileServerSn,shardCount);
}
}else{
//分片文件不存在或上传失败,则重新上传一次
action = true;
// console.log("重新上传")
//递归调用
upload(file,fileWholeId,fileWholeMd5,fileType,filePath,fileServerSn);
}
}else{
alert(result.msg);
}
},error: function(XMLHttpRequest, textStatus, errorThrown) {
alert("抱歉,请重试");
}
});
});
}
/**
* 所有分片文件上传成功后请求合并文件的方法
* @param fileWholeId 整体文件记录的id
* @param filePath 整体文件的存储路径
* @param fileServerSn 整体文件存储的文件服务器编号
* @param total 总分片数
*/
function mergeFile(fileWholeId , filePath , fileServerSn , total) {
var form = new FormData();
form.append("fileWholeId",fileWholeId);
form.append("filePath",filePath);
form.append("fileServerSn",fileServerSn);
form.append("total",total);
$.ajax({
url: "/upload/fileRecordTem/mergeFile",
type: "POST",
data: form,
async: false, //异步
processData: false, //很重要,告诉jquery不要对form进行处理
contentType: false, //很重要,指定为false才能形成正确的Content-Type
success: function(result){
console.log(result);
//合并成功
var data = result.data;
if(data != undefined && data){
alert("上传成功");
}else{
alert(result.msg);
}
},error: function(XMLHttpRequest, textStatus, errorThrown) {
alert("抱歉,请重试");
}
});
}
function uploadFile() {
document.getElementById("uploadButton").disabled = "disabled";
//获取要上传的文件对象
var files = document.getElementById("files").files;
//初始化数值
i = -1;
succeed = 0 ;
action = false;
isUpload(files[0]);
}
</script>
</body>
</html>
后端代码: