• 后端要采用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

  • 相关阅读:
    libevent中的bufferevent原理
    libevent中的事件机制
    libevent中数据缓冲区buffer分析
    libevent中最小堆实现算法解析
    我眼中的WebViewJavascriptBridge(图解)
    Tinyhttpd精读解析
    app微信支付的集成步骤
    java工厂模式的测试
    java Annotation 注解的使用
    android 连接蓝牙打印机 BluetoothAdapter
  • 原文地址:https://www.cnblogs.com/shenjp/p/13749816.html
Copyright © 2020-2023  润新知