js 大文件分割/分片上傳


 

 

<!DOCTYPE html>
<html>
  <head>
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>uploadFile</title>
    <style></style>
  </head>
  <body>
    <input type="file" id="file" multiple />
    <br />
    <br />
    <button id="btn">上傳</button>

    <script>
      var uploadFile;
      document.querySelector("#file").addEventListener(
        "change",
        (e) => {
          var files = e.target.files;
          if (!files.length) return;

          uploadFile = new CutFileAndUpload({
            files,
            apiUpload: (fileData) => {
              //接口請求 返回當前文件數據

              /**
             * fileData = {
                    file: file,  //當前文件
                    succeed: 0, //已經上傳的片數
                    shardSize: this.size, //以2MB為一個分片
                    shardCount: 0, //總片數
                    start: 0,  //截取開始位置
                    end: 0,  //截取結束位置
                }
            */

              //構造一個表單 表單字段根據后端接口而定
              let fdata = new FormData();
              //計算切割文件單個分片
              let base64 = fileData.file.slice(fileData.start, fileData.end);
              // fdata.append("base64", base64, fileData.file.name);
              // fdata.append("name", fileData.file.name);
              // fdata.append("total", fileData.shardCount); //總片數
              // fdata.append("numbers", fileData.succeed + 1); //當前是第幾片

              //接口請求
              setTimeout(() => {
                //更新文件數據
                uploadFile.updateFileData();
              }, 2000);
            },
            progress: (progress, total) => {
              //progress 當前文件進度百分比
              //total 總進度百分比
              console.log(progress, total);
            },
            success: () => {
              //上傳成功回調
              console.log("全部上傳完成");
              e.target.value = "";
            },
          });
        },
        false
      );
      document.querySelector("#btn").addEventListener(
        "click",
        () => {
          uploadFile.uploadFile();
        },
        false
      );

      /**
       *
       * @param {*} options
       */
      function CutFileAndUpload(options) {
        this.files = options.files || []; //要上傳的文件列表
        this.progress = options.progress; //上傳進度
        this.success = options.success; //成功回調
        this.apiUpload = options.apiUpload;

        this.fileArr = []; //文件列表切割后的文件數據
        this.fileIndex = 0; //上傳到第幾個文件
        this.size = 2 * 1024 * 1024; //分片單位 以2MB為一個分片
        this.uploading = false; //上傳狀態

        this.cutFile();
      }
      CutFileAndUpload.prototype = {
        constructor: CutFileAndUpload,
        cutFile() {
          var files = this.files;

          if (!files.length) {
            console.log("請選擇要上傳的文件");
            return;
          }

          for (var i = 0; i < files.length; i++) {
            var file = files[i];
            let fileData = {
              file: file,
              succeed: 0, //已經上傳的片數
              shardSize: this.size, //分片單位
              shardCount: 0, //總片數
              start: 0, //截取開始位置
              end: 0, //截取結束位置
            };
            fileData.shardCount = Math.ceil(
              fileData.file.size / fileData.shardSize
            ); //總片數
            this.fileArr.push(fileData);
          }
        },
        uploadFile() {
          if (!this.fileArr.length) {
            console.log("請選擇要上傳的文件");
            return;
          }

          var fileData = this.fileArr[this.fileIndex];
          //計算每一片的起始與結束位置
          fileData.start = fileData.succeed * fileData.shardSize;
          fileData.end = Math.min(
            fileData.file.size,
            fileData.start + fileData.shardSize
          );

          //計算文件單個分片
          // let base64 = fileData.file.slice(fileData.start, fileData.end);
          // console.log(fileData);

          this.uploading = true;

          //接口請求
          this.apiUpload && this.apiUpload(fileData);
        },
        updateFileData() {
          //更新文件數據
          var fileData = this.fileArr[this.fileIndex];
          fileData.succeed++;
          var progress = parseInt(
            (fileData.succeed / fileData.shardCount) * 100
          );
          var total;

          if (fileData.succeed === fileData.shardCount) {
            //單個文件上傳完成
            this.fileIndex++;
            total = parseInt((this.fileIndex / this.fileArr.length) * 100);
            this.progress && this.progress(progress, total);
            if (this.fileIndex == this.fileArr.length) {
              //列表的全部文件上傳完成
              this.uploading = false;
              this.fileIndex = 0;
              this.fileArr = [];
              this.success && this.success();
            } else {
              this.uploadFile();
            }
          } else {
            total = parseInt((this.fileIndex / this.fileArr.length) * 100);
            this.progress && this.progress(progress, total);
            this.uploadFile();
          }
        },
      };
    </script>
  </body>
</html>

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM