松鼠的博客

导航

js 大文件分割/分片上传

<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>uploadFile</title>
<style></style>
</head>
<body>
<input type="file" id="file" multiple />
<br />
<br />
<button id="btn">上传</button>

<script>
var uploadFile;
document.querySelector("#file").addEventListener(
"change",
(e) => {
var files = e.target.files;
if (!files.length) return;

uploadFile = new CutFileAndUpload({
files,
apiUpload: (fileData) => {
//接口请求 返回当前文件数据

/**
* fileData = {
file: file, //当前文件
succeed: 0, //已经上传的片数
shardSize: this.size, //以2MB为一个分片
shardCount: 0, //总片数
start: 0, //截取开始位置
end: 0, //截取结束位置
}
*/

//构造一个表单 表单字段根据后端接口而定
let fdata = new FormData();
//计算切割文件单个分片
let base64 = fileData.file.slice(fileData.start, fileData.end);
// fdata.append("base64", base64, fileData.file.name);
// fdata.append("name", fileData.file.name);
// fdata.append("total", fileData.shardCount); //总片数
// fdata.append("numbers", fileData.succeed + 1); //当前是第几片

//接口请求
setTimeout(() => {
//更新文件数据
uploadFile.updateFileData();
}, 2000);
},
progress: (progress, total) => {
//progress 当前文件进度百分比
//total 总进度百分比
console.log(progress, total);
},
success: () => {
//上传成功回调
console.log("全部上传完成");
e.target.value = "";
},
});
},
false
);
document.querySelector("#btn").addEventListener(
"click",
() => {
uploadFile.uploadFile();
},
false
);

/**
*
* @param {*} options
*/
function CutFileAndUpload(options) {
this.files = options.files || []; //要上传的文件列表
this.progress = options.progress; //上传进度
this.success = options.success; //成功回调
this.apiUpload = options.apiUpload;

this.fileArr = []; //文件列表切割后的文件数据
this.fileIndex = 0; //上传到第几个文件
this.size = 2 * 1024 * 1024; //分片单位 以2MB为一个分片
this.uploading = false; //上传状态

this.cutFile();
}
CutFileAndUpload.prototype = {
constructor: CutFileAndUpload,
cutFile() {
var files = this.files;

if (!files.length) {
console.log("请选择要上传的文件");
return;
}

for (var i = 0; i < files.length; i++) {
var file = files[i];
let fileData = {
file: file,
succeed: 0, //已经上传的片数
shardSize: this.size, //分片单位
shardCount: 0, //总片数
start: 0, //截取开始位置
end: 0, //截取结束位置
};
fileData.shardCount = Math.ceil(
fileData.file.size / fileData.shardSize
); //总片数
this.fileArr.push(fileData);
}
},
uploadFile() {
if (!this.fileArr.length) {
console.log("请选择要上传的文件");
return;
}

var fileData = this.fileArr[this.fileIndex];
//计算每一片的起始与结束位置
fileData.start = fileData.succeed * fileData.shardSize;
fileData.end = Math.min(
fileData.file.size,
fileData.start + fileData.shardSize
);

//计算文件单个分片
// let base64 = fileData.file.slice(fileData.start, fileData.end);
// console.log(fileData);

this.uploading = true;

//接口请求
this.apiUpload && this.apiUpload(fileData);
},
updateFileData() {
//更新文件数据
var fileData = this.fileArr[this.fileIndex];
fileData.succeed++;
var progress = parseInt(
(fileData.succeed / fileData.shardCount) * 100
);
var total;

if (fileData.succeed === fileData.shardCount) {
//单个文件上传完成
this.fileIndex++;
total = parseInt((this.fileIndex / this.fileArr.length) * 100);
this.progress && this.progress(progress, total);
if (this.fileIndex == this.fileArr.length) {
//列表的全部文件上传完成
this.uploading = false;
this.fileIndex = 0;
this.fileArr = [];
this.success && this.success();
} else {
this.uploadFile();
}
} else {
total = parseInt((this.fileIndex / this.fileArr.length) * 100);
this.progress && this.progress(progress, total);
this.uploadFile();
}
},
};
</script>
</body>
</html>

 

参考文章:http://blog.ncmem.com/wordpress/2023/11/14/js-%e5%a4%a7%e6%96%87%e4%bb%b6%e5%88%86%e5%89%b2-%e5%88%86%e7%89%87%e4%b8%8a%e4%bc%a0/

欢迎入群一起讨论

 

 

posted on 2023-11-14 17:48  Xproer-松鼠  阅读(180)  评论(0编辑  收藏  举报