后端要采用ArrayBuffer上傳文件


最近做了個不一樣的上傳方式,其實上傳文件是最常見的交互方式,前端上傳的方式也很多。常見的有:

1. form + input 上傳

<form action='uploadFile.php' enctype="multipart/form-data" type='post'>
  <input type='file'>
  <input type='hidden' name='userid'>
  <input type='hidden' name='signature'>
  <button>提交</button>
</form>

優點:使用簡單方便,兼容性好,基本所有瀏覽器都支持。

缺點:提交數據后頁面不會跳轉,前端無法知道什么時候上傳結束,傳輸別的參數需要借助 type="hidden" 來完成

2. 使用 FromData 上傳

使用js構造form表單的形式提交,簡單高效,也是現在比較流行的做法

<input type="file" id="file" />

<script>
let el = document.getElementById('file');
el.onchange = function(e) {
    const file = e.target.files[0];
    const formData = new FormData();
    formData.append("userid", userid);
    formData.append("signature", signature);
    formData.append("file", file);
}
</script>

缺點:不兼容IE10以下的瀏覽器

很遺憾。。我們的后端這兩種均不支持。。需要采用文件流的形式上傳

3. 采用ArrayBuffer 方式上傳

let el = document.getElementById('file');
el.onchange = function(e) {
    const file = e.target.files[0];
    const reader = new FileReader();
    reader.onload = async (e) => {
      const buffer = reader.result; // 獲取到一個文件的Arraybuffer
      this.uploadBuffer(buffer); // 上傳文件
    };
    reader.readAsArrayBuffer(file);
}

以上寫法看起沒什么問題。。也能正常上傳。但是文件超過10M以上的數據,就會卡死。如果文件更大,瀏覽器就直接崩潰了

這時就需要將ArrayBuffer 進行切片上傳

async uploadBuffer (buffer, startSzie = 0, index = 1) {
      let endSize = index * this.chunkSize;
      let res = buffer.slice(startSzie, endSize);
      try {
        // 上傳視頻片段
        const { data } = await axios({
          url: this.uploadUrl,
          method: 'post',
          data: res,
          headers: {
            'Content-Type': '',
            'Content-Range': `bytes ${startSzie}-${index * this.chunkSize}/${this.videoSzie}`
          }
        });
        const { start, path, success } = data;
        if (success) {
          // 如果還有剩余,則遞歸上傳,接口不支持並發
          if (endSize <= this.videoSzie) {
            this.uploadBuffer(buffer, start, ++index);
          } else {this.uploadSuccess = true;
            const params = {
              userId: this.userId,
              author: this.userName,
              name: this.videoFileName,
              filePath: path,
              serverId: this.serverId,
              type: 1
            };
            // 全部片段上傳成功之后,保存視頻
            const saveInfo = await IO.saveVideoInfo(params);
            if (saveInfo.list) {
              this.videoUrl.url = saveInfo.list;
            }
          }
        }
      } catch (error) {
        this.$toast('視頻上傳失敗');
        this.closeVideo();this.uploadSuccess = true;
      }
    }

缺點:大文件上傳會導致瀏覽器崩潰, 無法添加其他參數。上傳相對較慢

兼容性還可以。基本能滿足我們現在的業務場景

 

 

參考:

  https://developer.mozilla.org/zh-CN/docs/Web/API/FileReader/readAsArrayBuffer

  https://www.w3cschool.cn/javascript_guide/javascript_guide-d2h126ad.html

 


免責聲明!

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



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