话不多说直接上代码
import http from "./http";
import { BASE_URL } from "./common";
import { Loading } from "element-ui";
var percent = 0;
//视频分片上传方法封装,也适用于大图片
export async function uploadVedio(file) {
return new Promise((resolve, reject) => {
console.log("fileeee", file);
let duration = "",
title = file.name,
time = +new Date();
let url = URL.createObjectURL(file);
let audioElement = new Audio(url);
audioElement.addEventListener("loadedmetadata", _event => {
duration = Math.round(audioElement.duration);
});
let pz = {
maxSize: 1024 * 1024 * 2000, //文件大小限制20M
bufferSize: 1024 * 512, //单个分片大小
blocks: [], //分片数据集合
blockName: "newfile", //表单 file 的名字
filename: "", //上传的本地文件真实文件名
threadNum: 10, //上传线程数量
reset: function(fname) {
this.blocks = [];
this.filename = fname;
}
};
let upload_index = 0;
let upload_activeThreadCount = 0; //当前活跃线程数量
let upload_sendedBlockCount = 0; //已上传的block数量
afterselect(file);
async function afterselect(file) {
// if (document.getElementById("x").files.length < 1) {
// return false;
// }
// var file = document.getElementById("x").files[0];
//限制文件大小
// if (file.size > this.pz.maxSize) {
// this.showmsg(
// "文件大小限制:" + this.pz.maxSize + ",实际文件大小:" + file.size
// );
// return;
// }
pz.reset(file.name);
upload_index = upload_activeThreadCount = upload_sendedBlockCount = 0;
var endByte = 0,
startByte = 0;
while (true) {
startByte = endByte;
if (endByte + pz.bufferSize >= file.size) {
endByte = file.size;
} else {
endByte = endByte + pz.bufferSize;
}
var block = sliceFile(file, startByte, endByte);
if (!block) {
console.log("分片失败");
return;
}
pz.blocks.push(block);
if (endByte >= file.size) {
break;
}
}
var dis = Math.min(pz.threadNum, pz.blocks.length);
for (var i = 0; i < dis; i++) {
(i => {
setTimeout(async () => {
upload_activeThreadCount++;
fenpei(i);
}, 500);
})(i);
}
}
//只要是操作主线程中的变量或其他,就一定会自动同步到主线程来。相当于自动lock()
async function fenpei(i) {
//参数:线程名
if (upload_index >= pz.blocks.length) {
upload_activeThreadCount--;
if (upload_activeThreadCount == 0) {
combineFile();
}
return;
}
uploadBlock(i, upload_index);
upload_index++;
}
//发送拼接分块命令
async function combineFile() {
var fd1 = new FormData();
fd1.append("act", "combine"); //文件
fd1.append("chunks", pz.blocks.length); //文件名
fd1.append("filename", pz.filename); //分片索引
fd1.append("time", time);
const res = await http.post("/home/upload/upVideo", fd1);
resolve(res.data.url);
}
//显示进度
function showPercent() {
percent = parseInt((upload_sendedBlockCount / pz.blocks.length) * 100);
// console.log("percent", percent);
if (percent > 100) {
percent = 100;
}
}
//上传一个分片
async function uploadBlock(i, index) {
var chunk = index;
var fd = new FormData();
fd.append("newfile", pz.blocks[chunk]); //文件
fd.append("filename", pz.filename); //文件名
fd.append("chunk", chunk); //分片索引
fd.append("time", time);
fd.append("chunks", pz.blocks.length); //分片总数
let config = {
headers: {
"Content-Type": "multipart/form-data"
}
};
http
.post("/home/upload/upVideo", fd, config)
.then(() => {
console.log("单个分片", "chunk", chunk);
upload_sendedBlockCount++;
showPercent();
fenpei(i);
})
.catch(async e => {
console.log("出错了", e, "chunk", chunk);
var fd2 = new FormData();
fd2.append("newfile", pz.blocks[chunk]); //文件
fd2.append("filename", pz.filename); //文件名
fd2.append("chunk", chunk); //分片索引
fd2.append("time", time);
fd2.append("chunks", pz.blocks.length); //分片总数
let config = {
headers: {
"Content-Type": "multipart/form-data"
}
};
const res = await http.post("/home/upload/upVideo", fd2, config);
upload_sendedBlockCount++;
showPercent();
fenpei(i);
console.log("重新上传成功", "chunk", chunk);
});
}
//分割file成分片
function sliceFile(file, startByte, endByte) {
if (file.slice) {
return file.slice(startByte, endByte);
}
if (file.webkitSlice) {
return file.webkitSlice(startByte, endByte);
}
if (file.mozSlice) {
return file.mozSlice(startByte, endByte);
}
return null;
}
});
}
使用方法
在你需要的页面引入
import { uploadVedio } from "@/util/upload.js";
async changeUploadZip(e) {
let name = e.target.files[0].name;
//判断文件格式
if (!name.endsWith("zip") && !name.endsWith("rar")) {
this.$message.warning("请上传rar或者zip格式的文件");
return false;
}
this.zipName = e.target.files[0].name;
this.loadingZip = true;
//调用分片上传
let path = await uploadVedio(e.target.files[0], 1);
this.loadingZip = false;
this.ruleForm.zip = path;
},