web
由于自己测试用不考虑美观问题直接用 html 元素,没有在乎样式问题进度条,以及切片完成后的提示,可以提交切片,等等样式页面问题都没有去做完善:)
<div>
<input id="file2" type="file" , name="file2" onchange="change()" />
<button id="upLoad" type="submit" onclick="upload()">upload</button>
</div>
js 部分 我用提交数据使用 fetch 方法具体使用 请移步 mdn,
具体思路如下
- 获取文件将其切片
- 将切片文件上传之后台
- 告知文件上传完成
// 改变 input file
async function change() {
const [file] = document.getElementById("file2").files;
if (!file) return;
// console.log(file);
let cur = 0;
const SIZE = 1 * 1024 * 1024;
let fileChunkList = [];
const TOTAL = Math.ceil(file.size / SIZE);
while (cur < file.size) {
fileChunkList.push({ file: file.slice(cur, cur + SIZE) });
cur += SIZE;
}
// console.log(fileChunkList);
fileChunkList.forEach((value, index) => {
let fd = new FormData();
fd.append("files", value.file);
fd.append("cur", index);
fd.append("name", file.name);
fd.append("total", TOTAL);
fetch("upload/aaa", {
method: "post",
body: fd
})
.then(response => console.log(response))
.catch(error => console.error("Error:", error));
});
alert("切片完成,并提交后台。。");
}
// 切片完成,提交按钮
function upload() {
var data = { name: "123.mp4" };
fetch("upload/aaa2", {
method: "post",
body: JSON.stringify(data), // data can be `string` or {object}!
headers: {
"Content-Type": "application/json"
}
})
.then(response => console.log(response))
.catch(error => console.error("Error:", error));
}
nodeJS(Express)
具体思路如下
- 接收 web 传来等切片文件 ,使用 formidable 插件接收 formdata 数据
- 将获取的 formdata 放入 arr 对象,根据 cur 进行排序,避免合并的时候合并顺序混乱
- 将文件合并用 pipe
// 获取提交文件
router.post("/aaa", (req, res) => {
var form = new formidable.IncomingForm();
form.uploadDir = __dirname + "/../videos/";
form.keepExtensions = true;
form.parse(req, function(err, fields, files) {
if (err) return;
// console.log("fields", fields);
// console.log("files", files);
arr.push({
name: fields.name,
cur: fields.cur,
total: fields.total,
path: files.files.path
});
/**
* 排序根据 cur判断M
* @param 0 开始
*/
arr.sort((a, b) => a.cur - b.cur);
// console.log(arr);
res.send(msg.success("ok"));
});
});
// 获取合并信息
router.post("/aaa2", (req, res) => {
// 需要合并的数组
const checkList = arr.filter(v => v.name === req.body.name);
arr = arr.filter(v => v.name !== req.body.name);
const [item] = checkList;
// 文件名称
const NAME = item.name;
// 写入流
const writeStream = fs.createWriteStream(__dirname + "/../videos/" + NAME);
merage(checkList, writeStream);
res.json(msg.success());
});
// *合并文件
async function merage(checkList, writeStream) {
// *一定要同步合并 不能异步
for (const iterator of checkList) {
// 写入
await pipeStream(iterator, writeStream);
}
}
// 写入流
const pipeStream = (iterator, writeStream) =>
new Promise(resolve => {
const readStream = fs.createReadStream(iterator.path);
readStream.pipe(writeStream, { end: false });
// 读取结束 删除文件
readStream.on("end", () => {
// 删除文件
fs.unlinkSync(iterator.path);
console.log("文件已删除", iterator.path);
resolve();
});
});