nodejs
服务端 body解析用的是const formidableMiddleware = require("express-formidable");
/**
* 切片上传
*
*/
const PATH = require("path");
const FS = require("fs");
const mkDir = require("./ApiMkDir"); // 创建目录的封装方法
module.exports = function (req, res, config) {
return new Promise((resolve, reject) => {
// 获取时间
// 生成储存目录名称
let date = new Date();
let path = `${date.getFullYear()}${date.getMonth() + 1}${date.getDate()}`;
// 文件目录
let savePath = PATH.resolve(config.root, "assets/" + path);
let cachePath = PATH.resolve(config.root, "cacheUploads");
// 判断目录是否存在,不存在创建目录
if (!FS.existsSync(savePath)) mkDir(savePath);
if (!FS.existsSync(cachePath)) mkDir(cachePath);
// 获取分片数据
let { index, total, md5 } = req.fields;
// 临时文件路径
let TmpFileName = cachePath + "/" + req.files["file"].name;
// 存储文件路径
let FileName = savePath + "/" + req.files["file"].name;
// 当前文件传输进度管理
let TmpFileNameMange = cachePath + "/" + req.files["file"].name + ".txt";
TmpFileName = PATH.normalize(TmpFileName);
TmpFileNameMange = PATH.normalize(TmpFileNameMange);
FileName = PATH.normalize(FileName);
// 是否第一次传输
if (FS.existsSync(FileName)) FS.unlinkSync(FileName);
if (FS.existsSync(TmpFileNameMange)) {
let test = FS.readFileSync(TmpFileNameMange, { encoding: "utf-8" });
if (test) {
let { i, md5: md } = JSON.parse(test);
if (md === md5 && Number(i) > Number(index)) {
resolve(i);
return;
}
}
}
// 获取上传的文件buffer
let buffer = FS.readFileSync(req.files["file"].path);
// 写入临时文件
if (FS.appendFileSync(TmpFileName, buffer)) reject();
// 传输完成,移动到保存目录
// 写入保存文件
FS.writeFileSync(
TmpFileNameMange,
JSON.stringify({ i: index, total, md5 })
);
if (index === total) {
FS.renameSync(TmpFileName, FileName);
FS.unlinkSync(TmpFileNameMange);
resolve();
return;
}
resolve(index);
});
};
前端js代码
async submit() {
let file = this.$refs.file.files[0];
this.upload(file);
},
async upload(file, index = 0) {
// 获取文件大小
let fileSize = file.size;
// 每个块的大小
let chunkSize = 1024 * 1024 * 0.0005;
// 共多少块
let chunkNum = Math.ceil(fileSize / chunkSize);
// 定义formData对象
let formData = new FormData();
// 定义结束位置;
let end = index + 1;
// 片段是否最后一片,如果不是最后一片,那么就是每片的位置
if (end < chunkNum) end = end * chunkSize;
// 如果是最后一片,结束位置等于文件最后的位置
else end = fileSize;
// 获取单个切片
let chunData = file.slice(index * chunkSize, end);
// 储存单个切片
formData.append("file", chunData, file.name);
formData.append("index", index + 1); //第几片
formData.append("total", chunkNum); //第几片
formData.append('md5',md5(file))
let { data } = await axios({
url: "http://127.0.0.1:3000/api/chunkUpload",
method: "post",
data: formData,
headers: { token: "token" }
});
// 后台需要返回当前切片位置
index = data.data - 0;
if (end < fileSize) this.upload(file, index);
}
网友评论