切片上傳_根據(jù)文件頭判斷文件類型_分片合并下載

<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8" />
  <title></title>
</head>
<body>
  <input type="file" id="file" onchange="fileChange(this)" />
  <button onclick="download()">download</button>
  <script type="text/javascript">
    let fileData = [];
    let file

  async function fileChange (e) {
    if (e.files.length > 0 && (await valid(e.files[0], "jpg,png,gif"))) {
      file = e.files[0]
      let blobArray = sliceUp(e.files[0], 10 * 1024);
      sendblob(blobArray, 5, e.files[0].size);
    }
  }

  function sliceUp (blob, bytesPerPiece = 5 * 1024 * 1024) {
      let start = 0,
        end = 0,
        index = 0,
        filesize = blob.size,
        blobArray = [];
      //計算文件切片總數(shù)
      const totalPieces = Math.ceil(filesize / bytesPerPiece);
      while (index < totalPieces) {
      start = index * bytesPerPiece;
      //++index === totalPieces  最后一片
      end = ++index === totalPieces ? filesize : index * bytesPerPiece;
      const chunk = blob.slice(start, end); //切割文件
      blobArray.push({
        file: chunk,
        name: `${blob.name}(${index})`,
        type: blob.type,
      });
    }
    return blobArray;
  }

  //模擬axios上傳
  let _http = (data, ...config) => {
    console.log(data);
   return new Promise((resolve, reject) => {
      setTimeout(() => {
        resolve(data);
      }, 200);
    });
  };

  function sendblob (blobArray, num, totalSize) {
    // totalSize用來計算總進度 progressObj存儲每一片的上傳進度
    let progressObj = {};
    //計算進度條
    function computeProgress (key, loaded, total) {
      progressObj[key] = {
        loaded,
        total,
        issuccess: loaded === total,
        key,
      };
      let progress = 0;
      if (progressObj) {
        for (key in progressObj) {
          progress += progressObj[key].loaded;
        }
      }
    if (totalSize > progress && progress > 0) {
      return (progress / totalSize) * 100 + "%";
    }
    return "0%";
  }
  //遞歸上傳,每次五條,成功后繼續(xù)
  function send (fncarray) {
    return Promise.all(
      fncarray.map((blob) =>
        _http(blob, {
          onUploadProgress: (progressEvent) => {
            computeProgress(
              blob.name,
              progressEvent.loaded,
              progressEvent.total
            );
          },
        })
      )
    ).then((list) => {
      fileData = fileData.concat(list)
      blobArray.splice(0, num);
      if (blobArray.length > 0) {
        send(blobArray.slice(0, num));
      } else {
        console.log('end');
      }
    });
  }
  send(blobArray.slice(0, num));
}

async function valid (file, accept) {
  //根據(jù)文件頭驗證文件類型
  if (!file instanceof Blob) {
    throw Error("僅支持Blob驗證");
    // return false
  }
  if (!accept) return;
  const Ext2Hex = {
    jpg: /^(ffd8ffe)[0-4]{1}/,
    png: /^(89504e47){1}/,
    ico: /^(100){1}/,
    gif: /^(47494638){1}/,
  };
  let first4Byte = new DataView(await file.arrayBuffer()).getUint32(
    0,
    false
  );

  const uint32 = Number(first4Byte).toString(16);

  return Object.keys(Ext2Hex).some((key) => {
    if (accept.indexOf(key) > -1) {
      return Ext2Hex[key].test(uint32);
    }
  });
}


function getFile (fileIds, num) {
  let blobs = []
  function getHttpFile (ids) {
    return Promise.all(
      ids.map((name) =>
        _http(name, {
          onUploadProgress: (progressEvent) => { },
        }).then(name => {
          return fileData.find(e => e.name === name)
        })
      )
    ).then(async (list) => {
      blobs = blobs.concat(list)
      fileIds.splice(0, 5);
      if (fileIds.length > 0) {
        await getHttpFile(fileIds.slice(0, 5))
      } else {
        console.log('end');
      }
      return blobs
    });
  }
  return getHttpFile(fileIds.slice(0, 5))
}
//模擬分片下載
function download () {
  // 調(diào)接口獲取文件信息,根據(jù)大小去判斷是否分片獲取
  // 模擬直接使用上傳時賦值的 file
  if (file.size > 10 * 1024) {
    const fileIds = fileData.map(e => e.name);//fileIds 模擬file分割出的文檔碎片id/name
    getFile(fileIds, 5).then(blobs => {   //獲取文件碎片,每次發(fā)5條請求
      const blob = new Blob(blobs.map(e => e.file), {
        type: blobs[0].type
      });
      exprotStart(blob)
    })
  }
}
function exprotStart (blob, name) {
  const link = document.createElement('a');
  link.href = window.URL.createObjectURL(blob);
  link.download = name || Date.now();;
  link.click();
  window.URL.revokeObjectURL(link.href);
}
</script>
</body>
</html>
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容