大文件切片上传处理

上传js文件

import axios from "axios";
import SparkMD5 from "spark-md5";
//正常上传
const upload = (url, data, headers = {}) => {
  return new Promise((resolve, reject) => {
    axios({
      url,
      method: "post",
      data,
      headers: {
        ...headers,
        "Content-Type": "multipart/form-data",
      },
    })
      .then((res) => {
        return resolve(res.data);
      })
      .catch((err) => {
        return reject(err);
      });
  });
};
//分片上传
const uploadByPieces = async (url, { fileName, file }) => {
  // 变量
  const chunkSize = 5 * 1024 * 1024; // 5MB一片
  const chunkCount = Math.ceil(file.size / chunkSize); // 总片数
  const fileMd5 = await getFileMd5(file);
  // 获取当前chunk
  const getChunkInfo = (file, index) => {
    let start = index * chunkSize;
    let end = Math.min(file.size, start + chunkSize);
    let chunk = file.slice(start, end);
    return { start, end, chunk };
  };
  // 分片上传
  const uploadChunk = (data) => {
    return new Promise((resolve, reject) => {
      axios({
        url,
        method: "post",
        data,
        headers: {
          "Content-Type": "multipart/form-data",
        },
      })
        .then((res) => {
          return resolve(res.data);
        })
        .catch((err) => {
          return reject(err);
        });
    });
  };
  // 单个chunk上传
  const readChunk = async (index) => {
    const { chunk } = getChunkInfo(file, index);
    let fetchForm = new FormData();
    const chunkMd5 = await getFileMd5(chunk);
    // chunkNumber(索引编号)              index
    // identifier(md5)
    // chunkSize(块大小)                  chunkSize
    // currentChunkSize(当前块大小)       chunk.size
    // totalSize(总大小)                  file.size
    // totalChunks(块总数)                chunkCount
    // fileName(MD5-索引)                 identifier-index
    // type(csv)                          csv
    // file(文件块)                       chunk

    fetchForm.append("chunkNumber", index);
    fetchForm.append("identifier", fileMd5);
    fetchForm.append("chunkSize", chunkSize);
    fetchForm.append("currentChunkSize", chunk.size);
    fetchForm.append("totalSize", file.size);
    fetchForm.append("totalChunks", chunkCount);
    fetchForm.append("fileName", chunkMd5 + "-" + index);
    fetchForm.append("type", "csv");
    fetchForm.append("file", chunk);

    // 打印切片内容
    // for (var item of fetchForm.entries()) {
    //   console.log(item[0] + ", " + item[1]);
    // }
    // console.log("-----------------------");
    // return;
    return uploadChunk(fetchForm);
  };
  // 针对每个文件进行chunk处理
  const promiseList = [];
  try {
    for (let index = 0; index < chunkCount; ++index) {
      promiseList.push(readChunk(index));
    }
    const res = await Promise.all(promiseList);
    return { res, fileMd5 };
  } catch (e) {
    return e;
  }
};
/**
 * 获取文件MD5
 * @param file
 * @returns {Promise<unknown>}
 */
function getFileMd5(file) {
  let fileReader = new FileReader();
  fileReader.readAsBinaryString(file);
  let spark = new SparkMD5();
  return new Promise((resolve) => {
    fileReader.onload = (e) => {
      spark.appendBinary(e.target.result);
      resolve(spark.end() + Date.now());
    };
  });
}

export { upload, uploadByPieces, getFileMd5 };

调用上传方法

    beforeFileUpload(file) {
      if (file.size < 5 * 1024 * 1024) {
        this.commonUpload();
      } else {
        this.piecesUpload(file);
      }
      return false;
    },
    // 分片上传
    async piecesUpload(file, isVerifiableSource = false) {
      let url = "/api/xxxxx";
      let data = {
        file,
        fileName: file.name,
      };

      const loading =
        this.$eleUtils.openFullScreenLoading("该文件较大,请耐心等待...");
      const res = await uploadByPieces(url, data);
      loading.close();
      console.log(res);
      // 调用合并文件接口
      this.mergeFile(file, res.fileMd5, isVerifiableSource);
    },

html代码

<el-upload
  action=""
  accept=".csv"
  :multiple="false"
  :limit="1"
  :show-file-list="false"
  :before-upload="beforeFileUpload"
>
   <el-button size="small" type="primary">点击上传</el-button>
   <div slot="tip" class="el-upload__tip">提示</div>
</el-upload>
posted @ 2022-08-14 20:28  Li_pk  阅读(114)  评论(0编辑  收藏  举报