Javascript 如何使用Web Worker加速文件传输

Javascript 如何使用Web Worker加速文件传输,javascript,web-worker,data-transfer,Javascript,Web Worker,Data Transfer,我尝试将视频文件传输到名为“INFURA”的公共服务器 但是比我想象的要慢。(关于您是否认为问题在于您的CPU无法计算要发送的数据?您的CPU在这里几乎没有任何作用。罪魁祸首是在网络中。您的服务器或ISP的带宽将是限制设置者。我真诚地怀疑并行请求是否会加快速度。请注意,请求不是在与你的js相同的线程,如果你不事先对数据进行任何处理,你将不会从工作人员那里获得任何好处。@Kaido非常感谢你的回复。因为我的英语很差,我不确定你的意思是低速不是与web工作人员无关,只是与带宽有关。那么,我可以尝试解

我尝试将视频文件传输到名为“INFURA”的公共服务器


但是比我想象的要慢。(关于您是否认为问题在于您的CPU无法计算要发送的数据?您的CPU在这里几乎没有任何作用。罪魁祸首是在网络中。您的服务器或ISP的带宽将是限制设置者。我真诚地怀疑并行请求是否会加快速度。请注意,请求不是在与你的js相同的线程,如果你不事先对数据进行任何处理,你将不会从工作人员那里获得任何好处。@Kaido非常感谢你的回复。因为我的英语很差,我不确定你的意思是低速不是与web工作人员无关,只是与带宽有关。那么,我可以尝试解决这个问题吗?这确实是我想要的我的意思是,虽然我必须承认,我不知道是否有解决方案可以加快速度,但我怀疑将您的请求分块是其中之一,而且我很确定员工不会这样做。@kaido谢谢您,非常感谢您。这真的很有帮助,因为我还没有阅读完整的代码,但有几点您需要知道。一:我明白了这是对浏览器中活动连接数量的限制,创建超过此限制的上载流是毫无意义的。就此而言,创建多个上载流是毫无意义的。第二:上载原始二进制数据使用很少的CPU,使用辅助线程几乎没有什么好处。第三:不能100%保证每个辅助线程都是真正的系统线程,o只知道它们会被彼此沙盒。此外,即使它们是真正的操作系统线程,每个CPU核心超过1个也没有意义。你是否认为问题在于你的CPU无法计算要发送的数据?你的CPU在这里几乎没有任何事可做。罪魁祸首是网络。你的服务器或ISP的带宽w我将是限制设定者。我真诚地怀疑并行请求是否会使任何事情更快。请注意,请求不是在与js相同的线程上进行的,如果您不在手头上对数据进行任何处理,您将不会从工作人员那里获得任何好处。@Kaido非常感谢您的回复。因为我的英语很差,我不确定你的意思是,低速度与网络工作者无关,而与带宽有关。那么,我是否可以尝试解决这一问题?这确实是我要说的,虽然我必须承认,我不知道是否有解决方案可以加快速度,但我怀疑将你的请求分块是其中之一,我非常确定工作者不会uch。这对meI来说真的很有帮助,因为她还没有读到完整的代码,但有几点你需要知道。第一:浏览器中活动连接的数量有限制,创建比这个限制更多的上传流是没有意义的。就这一点而言,创建多个上传流是没有意义的。第二:上传原始二进制数据使用很少第三:不能100%保证每个工作线程都是一个真正的系统线程,只能保证它们彼此之间是沙盒。此外,即使它们是真正的操作系统线程,每个CPU核的收益也没有意义。
index.html

<!DOCTYPE html>
<html>

<head>
  <title></title>

  <!-- loading the minified version -->
  <script src="https://unpkg.com/ipfs/dist/index.min.js"></script>
  <script src="https://unpkg.com/ipfs-http-client/dist/index.min.js"></script>
  <script src="https://unpkg.com/ipfs-api@9.0.0/dist/index.js" integrity="sha384-5bXRcW9kyxxnSMbOoHzraqa7Z0PQWIao+cgeg327zit1hz5LZCEbIMx/LWKPReuB" crossorigin="anonymous"></script>
  <script src="https://code.jquery.com/jquery-3.4.1.min.js" integrity="sha256-CSXorXvZcTkaix6Yvo6HppcZGetbYMGWSFlBw8HfCJo=" crossorigin="anonymous"></script>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/bignumber.js/9.0.0/bignumber.js" integrity="sha256-TYZ2kR74G+TqMIiLuKpB57VUTNKhGFknyOKgRYqxhnw=" crossorigin="anonymous"></script>


</head>

<body>

  <h1 id="title">IPFS Client TEST (Infura)</h1>

  <select id="ipfs_client">
    <option value="infura" selected="selected">infura</option>
    <option value="private_gateway">private gateway</option>
  </select>

  <select id="num_of_chunks">
    <option value="1" selected="selected">1</option>
    <option value="2">2</option>
    <option value="3">3</option>
    <option value="4">4</option>
    <option value="5">5</option>
    <option value="6">6</option>
    <option value="7">7</option>
    <option value="8">8</option>
    <option value="9">9</option>
    <option value="10">10</option>

  </select>

  <div id="" style="margin-top:40px">
    <h2>file upload</h2>
    <input type="file" id="file" onchange="loadFile(event)" />
    <input type="button" value="upload" id="send_ipfs" onclick="javascript:sendIpfs();" />
    <input type="button" value="upload_webworker" id="send_ipfs_webworker" onclick="javascript:sendIpfsWebWorker();" />
    <a id="file_url"></a>

  </div>

  <div id="" style="margin-top:40px">
    <h2> file download </h2>
    <input type="text" id="downloadHash" placeholder="download hash" onchange="" />
    <input type="button" value="get" id="get_ipfs" onclick="javascript:getIpfs();" />
    <a id="linkToDownload" href="" download=""></a>

  </div>
  <div style="margin-top:80px">
    <h1>IPFS Node TEST (js-ipfs Node)</h1>
    <div id="" style="margin-top:40px">
      <h2>upload(browser Node) </h2>
      <input type="file" id="fileBrowserNode" onchange="loadFileForBrowserNode(event)" />
      <input type="button" value="upload" id="send_ipfs_to_browser_node" onclick="javascript:sendIpfsToBrowserNode()" />
      <a id="file_url"></a>

    </div>

    <div id="" style="margin-top:40px">
      <h2> download(browser Node) </h2>
      <input type="text" id="downloadHashBrowserNode" placeholder="download hash" onchange="" />
      <input type="button" value="get" id="get_ipfs_from_browser_node" onclick="javascript:getIpfsFromBrowserNode()" />
      <a id="linkToDownloadBrowserNode" href="" download=""></a>

    </div>

    <div id="" style="margin-top:40px">
      <h2> stat bandwidth </h2>
      TotalIn:<span id="bwTotalIn"></span><br>
      TotalOut:<span id="bwTotalOut"></span><br>
      RateIn:<span id="bwRateIn"></span><br>
      RateOut:<span id="bwRateOut"></span><br>
    </div>

    <div id="web_worker_test" style="margin-top:40px">
      <h2> Webworker Test </h2>
      ouput: <span id="web_worker_output"></span>
      <button id="worker_run" value="run">run</button>
    </div>
  </div>
</body>


<script>
  var downloadedfiles
  var onloadfile
  var numOfChunks = 0;
  var uploadBuf = new Array(numOfChunks);
  var downloadBuf = new Array(numOfChunks);
  var fullLength
  var ipfs = new Array(numOfChunks)
  var uploadedChunkCnt = 0
  var hashBuffer = new Array(numOfChunks)
  var worker = new Array();
  var uploadStartTime
  $(document).ready(function() {
    numOfChunks = $('#num_of_chunks').val()

    chooseClient = function() {
      var selectedClient = $('#ipfs_client').val();
      console.log(selectedClient);
      if (selectedClient == 'infura') {
        for (var i = 0; i < numOfChunks; i++) {
          ipfs[i] = window.IpfsHttpClient({
            host: 'ipfs.infura.io',
            port: 5001,
            protocol: 'https'
          });
        }
        $('#title').html('IPFS Client TEST (Infura)');
      } else if (selectedClient == 'private_gateway') {
        ipfs = window.IpfsHttpClient({
          host: 'devipfs.nemodax.com',
          port: 5001,
          protocol: 'https'
        })
        $('#title').html('IPFS Client TEST (devipfs Private Gateway)');
      }
    }


    function init() {
      numOfChunks = $('#num_of_chunks').val()

      worker = new Array()

      if (typeof(onloadfile) != 'undefined') {
        fullLength = onloadfile.result.byteLength;
        chunkLength = fullLength / numOfChunks
        for (var i = 0; i < numOfChunks; i++) {
          var chunk
          if (i == numOfChunks - 1) { // last chunk process
            chunk = onloadfile.result.slice(i * chunkLength, fullLength)
          } else {
            chunk = onloadfile.result.slice(i * chunkLength, (i + 1) * chunkLength)
          }
          uploadBuf[i] = Ipfs.Buffer(chunk)
        }
      }

      for (var i = 0; i < numOfChunks; i++) {

        worker.push(new Worker("./IPFSUpload_worker.js"))

        worker[i].onmessage = function(event) {
          uploadedChunkCnt += event.data.uploadedChunkCnt
          console.log("The number of Worker Thread which has done: ", uploadedChunkCnt);
          hashBuffer[event.data.thread_no] = event.data.hashBuffer
          if (uploadedChunkCnt == numOfChunks) {
            console.log("All chunks are downloaded. Creating indexHash on IPFS...")
            var chunkMap = ""
            for (var j = 0; j < numOfChunks; j++) {
              chunkMap = chunkMap + hashBuffer[j] + ','
            }
            ipfs[0].add(Ipfs.Buffer.from(chunkMap)).then((res) => {
              indexHash = res[0].hash
              var uploadFileSize = fullLength // byte
              var uploadEndTime = new Date();
              var uploadInterval = uploadEndTime - uploadStartTime // ms
              var uploadSpeed = uploadFileSize / uploadInterval // byte / ms == kb/s
              console.log('* upload hash:', indexHash)
              console.log('* chunkMap:', chunkMap);
              console.log('* upload path:', event.data.path)
              console.log('* upload size:', formatSizeUnits(uploadFileSize))
              console.log('* upload speed:', uploadSpeed, 'kb/s')
              console.log('* upload interval:', uploadInterval / 1000, 'sec')
            });
          }
        }
      }
      chooseClient()
    }


    $('#num_of_chunks').on('change', function() {
      for (var i = 0; i < numOfChunks; i++) {
        if (typeof(worker[i]) != 'undefined') {
          worker[i].terminate()
        }
      }
      init()
    })

    init();
  })

  function sendIpfsWebWorker() {
    uploadStartTime = new Date();
    var path = $("#file").val().split("\\")[2]
    console.log("> start upload (api): ", path, uploadStartTime)
    uploadedChunkCnt = 0;
    var params = new Array()
    for (var i = 0; i < numOfChunks; i++) {
      data = {
        "thread_no": i,
        //"ipfs": ipfs, // 메소드는 직렬화 할수 없다..
        "functionToCall": "",
        "selectedClient": $('#ipfs_client').val(),
        "numOfChunksInThread": 1,
        "uploadBuf": uploadBuf[i],
        "downloadBuf": downloadBuf[i],
        "fullLength": fullLength,
        "path": path,
        "uploadedChunkCnt": uploadedChunkCnt
        //results:,
        //hashBuffer:,
      }

      params.push(data)

      params[i] = JSON.parse(JSON.stringify(params[i]));
      worker[i].postMessage(params[i])
      //console.log(params[i])
      //console.log("stringify params:", params[i])
    }
    //console.log("stringify params:", params[0])
  }


  async function getBandWidth() {
    bw = await node.stats.bw()

    $('#bwTotalIn').html(formatSizeUnits(bw.totalIn.toString().slice(0, 5)));
    $('#bwTotalOut').html(formatSizeUnits(bw.totalOut.toString().slice(0, 5)));
    $('#bwRateIn').html(formatSizeUnits(bw.rateIn.toString().slice(0, 5)) + '/s');
    $('#bwRateOut').html(formatSizeUnits(bw.rateOut.toString().slice(0, 5)) + '/s');
  }




  const reader = new FileReader();

  var loadFile = function(event) {
    console.log('upload::');

    const reader = new FileReader();
    reader.onload = function() {
      console.log('onload::');

      onloadfile = reader
      //buf = Ipfs.Buffer(reader.result); // Convert data into buffer

      // split the file it will be uploaded

      fullLength = reader.result.byteLength;
      chunkLength = fullLength / numOfChunks

      for (var i = 0; i < numOfChunks; i++) {
        var chunk
        if (i == numOfChunks - 1) { // last chunk process
          chunk = reader.result.slice(i * chunkLength, fullLength)
        } else {
          chunk = reader.result.slice(i * chunkLength, (i + 1) * chunkLength)
        }
        uploadBuf[i] = Ipfs.Buffer(chunk)
      }

    };

    const file = document.getElementById("file");
    reader.readAsArrayBuffer(file.files[0]); // Read Provided File

  };





  async function sendIpfs() {

    var uploadStartTime = new Date();
    console.log("> start upload (api): ", uploadStartTime)

    var path = $("#file").val().split("\\")[2]

    results = new Array(numOfChunks)
    hashBuffer = new Array(numOfChunks)
    uploadedChunkCnt = 0;

    for (var i = 0; i < numOfChunks; i++) {
      var chunkStartTime = new Date();
      console.log("start upload chunk[", i, "](api): ", chunkStartTime)

      ipfs[i].add([{
        path: path + '.nemo.' + i,
        content: uploadBuf[i],
      }], {
        recursive: true,
        wrapWithDirectory: true
        //progress: (length) => {
        //  console.log(length);
        //}
      }).then((res) => {
        var token = res[0].path.split('.')
        var chunkNum = token[token.length - 1]
        results[chunkNum] = res;

        console.log(results[chunkNum]);
        var chunkEndTime = new Date();
        var chunkInterval = chunkEndTime - chunkStartTime // ms
        var chunkSize = uploadBuf[chunkNum].length // byte
        var speed = chunkSize / chunkInterval // byte / ms == kb/s
        console.log('interval upload chunk[', chunkNum, '](api): ', chunkInterval / 1000, 'size:', chunkSize / 1000, 'kb', speed, 'kb/s')

        hashBuffer[chunkNum] = results[chunkNum][1].hash;
        console.log(hashBuffer[chunkNum]);
        uploadedChunkCnt++;
        if (uploadedChunkCnt == numOfChunks) {
          var chunkMap = ""
          for (var j = 0; j < numOfChunks; j++) {
            chunkMap = chunkMap + hashBuffer[j] + ','
          }
          ipfs[0].add(Ipfs.Buffer.from(chunkMap)).then((res) => {
            indexHash = res[0].hash
            var uploadFileSize = fullLength // byte

            var uploadEndTime = new Date();
            var uploadInterval = uploadEndTime - uploadStartTime // ms
            var uploadSpeed = uploadFileSize / uploadInterval // byte / ms == kb/s
            console.log('* upload hash:', indexHash)
            console.log('* chunkMap:', chunkMap);
            console.log('* upload path:', path)
            console.log('* upload size:', formatSizeUnits(uploadFileSize))
            console.log('* upload speed:', uploadSpeed, 'kb/s')
            console.log('* upload interval:', uploadInterval / 1000, 'sec')
          });
        }
      })
    }
  }




  function formatSizeUnits(bytes) {
    if (bytes >= 1073741824) {
      bytes = (bytes / 1073741824).toFixed(2) + " GB";
    } else if (bytes >= 1048576) {
      bytes = (bytes / 1048576).toFixed(2) + " MB";
    } else if (bytes >= 1024) {
      bytes = (bytes / 1024).toFixed(2) + " KB";
    } else if (bytes > 1) {
      bytes = bytes + " bytes";
    } else if (bytes == 1) {
      bytes = bytes + " byte";
    } else {
      bytes = "0 bytes";
    }
    return bytes;
  }
</script>


</html>
IPFSUpload_worker.js


var window = {}
importScripts('./js/ipfs_index.js');
importScripts('./js/ipfs-http-client_index.js');
self.IpfsHttpClient = window.IpfsHttpClient
self.Ipfs = window.Ipfs


 function createClient(context) {

  context.ipfs = new Array(context.numOfChunksInThread)

  if (context.selectedClient == 'infura') {
    for (var i = 0; i < context.numOfChunksInThread; i++) {
      context.ipfs[i] = self.IpfsHttpClient({
        host: 'ipfs.infura.io',
        port: 5001,
        protocol: 'https'
      });
    }
  }
}


async function sendIpfsWebWorker(context) {
  createClient(context)
  console.log("context in worker: ", context)

  context.results = new Array(context.numOfChunksInThread)
  context.hashBuffer = new Array(context.numOfChunksInThread)
  context.uploadedChunkCnt = 0;


  for (var i = 0; i < context.numOfChunksInThread; i++) {
    var chunkStartTime = new Date();
    console.log("start upload chunk[", context.thread_no, "](api): ", chunkStartTime)

    context.ipfs[i].add([{
      path: context.path + '.nemo.' + context.thread_no,
      content: Ipfs.Buffer(context.uploadBuf.data),
    }], {
      recursive: true,
      wrapWithDirectory: true
      //progress: (length) => {
      //  console.log(length);
      //}
    }).then((res) => {
      var token = res[0].path.split('.')
      var chunkNum = token[token.length - 1]
      context.results[chunkNum] = res;

      console.log(context.results[chunkNum]);
      var chunkEndTime = new Date();
      var chunkInterval = chunkEndTime - chunkStartTime // ms
      var chunkSize = context.uploadBuf.data.length // byte
      var speed = chunkSize / chunkInterval // byte / ms == kb/s
      console.log('interval upload chunk[', chunkNum, '](api): ', chunkInterval / 1000, 'size:', chunkSize / 1000, 'kb', speed, 'kb/s')

      context.hashBuffer = context.results[chunkNum][1].hash;
      console.log(context.hashBuffer);
      context.uploadedChunkCnt++;

      var resultForMainThread = JSON.parse(JSON.stringify(context));
      postMessage(resultForMainThread);
      self.close()

    })
  }
}


function formatSizeUnits(bytes) {
  if (bytes >= 1073741824) {
    bytes = (bytes / 1073741824).toFixed(2) + " GB";
  } else if (bytes >= 1048576) {
    bytes = (bytes / 1048576).toFixed(2) + " MB";
  } else if (bytes >= 1024) {
    bytes = (bytes / 1024).toFixed(2) + " KB";
  } else if (bytes > 1) {
    bytes = bytes + " bytes";
  } else if (bytes == 1) {
    bytes = bytes + " byte";
  } else {
    bytes = "0 bytes";
  }
  return bytes;
}


onmessage = function(event){

  sendIpfsWebWorker(event.data);

}
index.html:275 upload::
index.html:279 onload::
index.html:197 > start upload (api):  harry_potter_hermione_growth_spurt_snl_720p.mp4 Fri Aug 16 2019 09:48:28 GMT+0900 (한국 표준시)
IPFSUpload_worker.js:39 context in worker:  {thread_no: 0, functionToCall: "", selectedClient: "infura", numOfChunksInThread: 1, uploadBuf: {…}, …}
IPFSUpload_worker.js:52 start upload chunk[ 0 ](api):  Fri Aug 16 2019 09:48:45 GMT+0900 (한국 표준시)
IPFSUpload_worker.js:68 (2) [{…}, {…}]
IPFSUpload_worker.js:73 interval upload chunk[ 0 ](api):  15.69 size: 51340.408 kb 3272.1738687061825 kb/s
IPFSUpload_worker.js:76 QmNqHoM9cyNeXH1QLUZt2sZtBY8DgoYB8aD7WFBHccK5VD
index.html:154 The number of Worker Thread which has done:  1
index.html:157 All chunks are downloaded. Creating indexHash on IPFS...
index.html:168 * upload hash: QmPYTrBBZVHPusoUP3oRsaD3T25ccY2LFbUYCgAUvkWuFP
index.html:169 * chunkMap: QmNqHoM9cyNeXH1QLUZt2sZtBY8DgoYB8aD7WFBHccK5VD,
index.html:170 * upload path: harry_potter_hermione_growth_spurt_snl_720p.mp4
index.html:171 * upload size: 48.96 MB
index.html:172 * upload speed: 904.9797817771589 kb/s
index.html:173 * upload interval: 56.731 sec
index.html:275 upload::
index.html:279 onload::
index.html:197 > start upload (api):  harry_potter_hermione_growth_spurt_snl_720p.mp4 Fri Aug 16 2019 09:55:30 GMT+0900 (한국 표준시)
IPFSUpload_worker.js:39 context in worker:  {thread_no: 0, functionToCall: "", selectedClient: "infura", numOfChunksInThread: 1, uploadBuf: {…}, …}
IPFSUpload_worker.js:52 start upload chunk[ 0 ](api):  Fri Aug 16 2019 09:55:33 GMT+0900 (한국 표준시)
IPFSUpload_worker.js:39 context in worker:  {thread_no: 1, functionToCall: "", selectedClient: "infura", numOfChunksInThread: 1, uploadBuf: {…}, …}
IPFSUpload_worker.js:52 start upload chunk[ 1 ](api):  Fri Aug 16 2019 09:55:35 GMT+0900 (한국 표준시)
IPFSUpload_worker.js:39 context in worker:  {thread_no: 2, functionToCall: "", selectedClient: "infura", numOfChunksInThread: 1, uploadBuf: {…}, …}
IPFSUpload_worker.js:52 start upload chunk[ 2 ](api):  Fri Aug 16 2019 09:55:37 GMT+0900 (한국 표준시)
IPFSUpload_worker.js:39 context in worker:  {thread_no: 3, functionToCall: "", selectedClient: "infura", numOfChunksInThread: 1, uploadBuf: {…}, …}
IPFSUpload_worker.js:52 start upload chunk[ 3 ](api):  Fri Aug 16 2019 09:55:39 GMT+0900 (한국 표준시)
IPFSUpload_worker.js:39 context in worker:  {thread_no: 4, functionToCall: "", selectedClient: "infura", numOfChunksInThread: 1, uploadBuf: {…}, …}
IPFSUpload_worker.js:52 start upload chunk[ 4 ](api):  Fri Aug 16 2019 09:55:42 GMT+0900 (한국 표준시)
IPFSUpload_worker.js:68 (2) [{…}, {…}]
IPFSUpload_worker.js:73 interval upload chunk[ 2 ](api):  16.813 size: 10268.081 kb 610.7227145661095 kb/s
IPFSUpload_worker.js:76 QmNzJqR3snVWQexVQA7crYNV4bJEjxMT9EHzhL5bSrBB5W
index.html:154 The number of Worker Thread which has done:  1
IPFSUpload_worker.js:68 (2) [{…}, {…}]
IPFSUpload_worker.js:73 interval upload chunk[ 0 ](api):  23.512 size: 10268.081 kb 436.71661279346716 kb/s
IPFSUpload_worker.js:76 QmSoruLfXkR51MVRUrcbBetGW4StkjfvxPAdn7yDoHdBUV
IPFSUpload_worker.js:68 (2) [{…}, {…}]
IPFSUpload_worker.js:73 interval upload chunk[ 3 ](api):  18.422 size: 10268.082 kb 557.3815003799805 kb/s
IPFSUpload_worker.js:76 QmY9KdJwnLsWcjYQCxNUECTFx82EhJf9CYBEZhQxqa38Ev
index.html:154 The number of Worker Thread which has done:  2
index.html:154 The number of Worker Thread which has done:  3
IPFSUpload_worker.js:68 (2) [{…}, {…}]
IPFSUpload_worker.js:73 interval upload chunk[ 1 ](api):  25.713 size: 10268.082 kb 399.3342667133357 kb/s
IPFSUpload_worker.js:76 Qmbx4svY1z6LhTje2gJinwQqNaDwjgt8fJsiNJh9fmSjnT
index.html:154 The number of Worker Thread which has done:  4
IPFSUpload_worker.js:68 (2) [{…}, {…}]
IPFSUpload_worker.js:73 interval upload chunk[ 4 ](api):  23.085 size: 10268.082 kb 444.79454191033136 kb/s
IPFSUpload_worker.js:76 QmeVYG86BNcqfhy6RjtGEM6dSFo33cfNFM4Ebniop4cAmf
index.html:154 The number of Worker Thread which has done:  5
index.html:157 All chunks are downloaded. Creating indexHash on IPFS...
index.html:168 * upload hash: QmdnbFQQJ4HhbvE2nNcJ9jhJmajGd83qdNxFkcQkgAXeNk
index.html:169 * chunkMap: QmSoruLfXkR51MVRUrcbBetGW4StkjfvxPAdn7yDoHdBUV,Qmbx4svY1z6LhTje2gJinwQqNaDwjgt8fJsiNJh9fmSjnT,QmNzJqR3snVWQexVQA7crYNV4bJEjxMT9EHzhL5bSrBB5W,QmY9KdJwnLsWcjYQCxNUECTFx82EhJf9CYBEZhQxqa38Ev,QmeVYG86BNcqfhy6RjtGEM6dSFo33cfNFM4Ebniop4cAmf,
index.html:170 * upload path: harry_potter_hermione_growth_spurt_snl_720p.mp4
index.html:171 * upload size: 48.96 MB
index.html:172 * upload speed: 1189.9503534592652 kb/s
index.html:173 * upload interval: 43.145 sec
for (var i = 0; i < numOfChunks; i++) {
          ipfs[i] = window.IpfsHttpClient({
            host: 'ipfs.infura.io',
            port: 5001,
            protocol: 'https',
          });
        }
...

for (var i = 0; i < numOfChunks; i++) {

ipfs[i].add([{
        path: path + '.nemo.' + i,
        content: uploadBuf[i],
      }], {
        recursive: true,
        wrapWithDirectory: true
      }).then((res) => {
        ... // do the job I intended.
      })
}