nodejs 切片断点续传

2021-04-13  本文已影响0人  芸芸众生ing

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);
    }
上一篇 下一篇

猜你喜欢

热点阅读