web前端大文件切片上传完整功能

105 阅读1分钟

前端大文件上传

      fetch("./fe3af85b9cf6201c415122532d3cc0ca.jpg").then((data) => {
        data.blob().then((data) => {
          handleUpload(data);
        });
      });
      const spark = new SparkMD5.ArrayBuffer();
      const handleUpload = async (file, chunkSize = 100 * 1024) => {
        const fileArrayBuffer = await file.arrayBuffer();
        // 获取完整文件的hash值
        const completeFileHash = SparkMD5.ArrayBuffer.hash(fileArrayBuffer);
        //获取上传的切片的个数
        const chunkNumber = Math.ceil(file.size / chunkSize);
        // 使用for await 按顺序上传切片文件
        for (let p = 0; p < chunkNumber; p++) {
          const chunkFile = file.slice(p * chunkSize, (p + 1) * chunkSize);
          const data = await uploadItem(chunkFile);
          // 计算文件上传进度
          const currentPercent = ((p + 1) / chunkNumber) * 100;
          spark.append(data);
        }
        // 对比前后两个hash值
        console.log(completeFileHash, spark.end());
      };
      const uploadItem = (file) => {
        // 模拟异步请求
        return fetchWithRetry("url", file)
          .then(async () => {
            const data = await file.arrayBuffer();
            return Promise.resolve(data);
          })
          .catch((err) => {
            confirm(err);
            return Promise.reject(err);
          });
      };
      // 断点抛错重新上传
      async function fetchWithRetry(url, data, maxRetries = 3) {
        let retries = 0;
        const formData = new FormData();
        formData.append("file", data);
        const options = {
          method: "post",
          body: formData,
        };
        while (retries < maxRetries) {
          try {
            const response = await fetch(url, options).then((res) => {
              if (!res.ok) {
                return Promise.reject("err");
              }
            });
            return response;
          } catch (error) {
            retries++;
          }
        }
        //超过最大次数抛出错误 提醒用户重新上传
        throw new Error("Max retries reached.");
      }