【问题标题】:Receive binary data in web browser from HTTP server in a streaming style在 Web 浏览器中以流式传输方式从 HTTP 服务器接收二进制数据
【发布时间】:2015-07-29 01:10:54
【问题描述】:

我正在寻找一种仅客户端的 JavaScript 解决方案,它可以以流式传输方式从 HTTP 服务器接收大型二进制文件到我的 Web 客户端,这样我可以在获得数据包后立即响应,而无需等待它们全部加载到内存中,我什至可以在处理完每个数据后丢弃数据,以减少内存占用。

我在网上搜索,发现通过 XMLHttpRequest 似乎不可能,原因有两个(引用自this article),

  • XHR 阻止在请求完成之前访问二进制响应(具有 arraybuffer 响应类型)数据。
  • XHR 响应本质上是一个大缓冲区,随着响应数据的到来,它会保持线性增长,这意味着它无法被垃圾收集。

我想知道这是否可以通过 websocket 实现,是否有任何好的开源已经解决了这个问题?我发现了一些看起来相关的东西,例如Oboe.jsBinary.js,但它要么处理 JSON 流,要么需要服务器端支持。

【问题讨论】:

  • 你有没有得到任何地方?我目前正在处理类似的问题。
  • @NickJennings 在下面看到我的回答,虽然它不是一个完整的解决方案,但它可以满足我的一些需求。

标签: javascript html web websocket xmlhttprequest


【解决方案1】:

使用 XMLHttpRequest 无法满足我的所有请求。但是,通过一些技巧,我可以在块二进制数据到达后读取它。一般来说,将 minetype 覆盖为 'text/plain; charset=x-user-defined' 它将二进制数据作为文本流式传输,一旦一个包准备就绪,我就可以获取它并将其转换为 arrayBuffer。

var xhr = new XMLHttpRequest();
var streamOffset = 0;

xhr.overrideMimeType('text/plain; charset=x-user-defined');
xhr.open("GET", url, true);
xhr.send();
xhr.onreadystatechange = function () {
    var textBuffer = xhr.responseText;
    var arrayBuffer = textToArrayBuffer(textBuffer, streamOffset);
}
function textToArrayBuffer(textBuffer, startOffset) {
    var len = textBuffer.length - startOffset;
    var arrayBuffer = new ArrayBuffer(len);
    var ui8a = new Uint8Array(arrayBuffer, 0);
    for (var i = 0, j = startOffset; i < len; i++, j++)
        ui8a[i] = (textBuffer.charCodeAt(j) & 0xff);
    return arrayBuffer;
}

尽管如此,我可以通过这种方式以流的方式获取二进制数据,但在处理完每个块之后,直到请求完成,它才能被丢弃。无论如何,这让我有机会在二进制数据到达后立即处理它。

【讨论】:

    【解决方案2】:

    现在,您可以使用Fetch API 来做到这一点。

    fetch() 的结果包含一个名为 body 的属性,它是一个可用于读取结果的ReadableStream

    fetch('https://example.fake/movies.csv')
      .then((fetchedData) => {
        const reader = fetchedData.body.getReader();
        readChunks(reader);
      });
    
    
    function readChunks(reader) {
      reader.read().then(({ done, value }) => {
        if (done) {
          console.log('done reading', value);
          return;
        }
    
        console.log('read chunk', value);
        readChunks(reader);
      });
    }
    

    【讨论】:

      猜你喜欢
      • 2016-06-24
      • 2016-09-07
      • 2021-12-08
      • 1970-01-01
      • 2023-03-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多