【问题标题】:HTTP POST using XHR with Chunked Transfer Encoding使用带有分块传输编码的 XHR 的 HTTP POST
【发布时间】:2021-11-18 04:56:47
【问题描述】:

我有一个 REST API,它通过 HTTP Post 接受音频文件。该 API 支持 Transfer-Encoding: 分块请求标头,以便文件可以在从客户端上运行的记录器创建时分段上传。这样,服务器可以在文件到达时开始处理文件以提高性能。例如:

HTTP 1.1 POST .../v1/processAudio

传输编码:分块

[Chunk 1 256 Bytes](服务器到达时开始处理)

[块 2 256 字节]

[块 3 256 字节]

...

音频文件通常很短,大小约为 10K 到 100K。我有 C# 和 Java 代码可以工作,所以我知道 API 可以工作。但是,我似乎无法使用 javascript 在浏览器中进行录制和上传。

这是我的测试代码,它使用传输编码对本地主机进行 POST:

<html>
<script type="text/javascript">
  function streamUpload() {
    var blob = new Blob(['GmnQPBU+nyRGER4JPAW4DjDQC19D']);
    var xhr = new XMLHttpRequest();
    // Add any event handlers here...
    xhr.open('POST', '/', true);
    xhr.setRequestHeader("Transfer-Encoding", "chunked");
    xhr.send(blob);
  }
</script>

<body>
  <div id='demo'>Test Chunked Upload using XHR</div>
  <button onclick="streamUpload()">Start Upload</button>
</body>

</html>

问题是我在 Chrome 中收到以下错误

拒绝设置不安全的标头“Transfer-Encoding”

streamUpload@uploadTest.html:14 onclick@uploadTest.html:24

查看 XHR 文档后,我仍然感到困惑,因为它没有谈论不安全的请求标头。我想知道 XHR 是否可能不允许或实现 HTTP POST 的 Transfer-Encoding: chunked

我查看了使用多个 XHR.send() 请求和 WebSockets 的变通方案,但两者都是不可取的,因为它需要对已经到位、简单、稳定和工作的服务器 API 进行重大更改。唯一的问题是我们似乎无法通过 Transfer-Encoding: 分块请求标头从具有伪流的浏览器进行 POST。

任何想法或建议都会非常有帮助。

【问题讨论】:

标签: javascript http xmlhttprequest transfer-encoding


【解决方案1】:

正如评论中提到的,您不能设置该标题,因为它由用户代理控制。

有关完整的标头集,请参阅 W3C XMLHttpRequest Level 1 中的 4.6.2 The setRequestHeader() method 并注意 Transfer-Encoding 是由用户代理控制的标头之一,以使其控制传输的这些方面。

  • 接受字符集
  • 接受编码
  • 访问控制请求标头
  • 访问控制请求方法
  • 连接
  • 内容长度
  • 饼干
  • Cookie2
  • 日期
  • DNT
  • 期待
  • 主机
  • 保持活动状态
  • 原产地
  • 参考
  • TE
  • 预告片
  • 传输编码
  • 升级
  • 用户代理
  • 通过

WhatWG Fetch API 生活标准中有一个类似的列表。 https://fetch.spec.whatwg.org/#terminology-headers

【讨论】:

    【解决方案2】:

    正如其他回复已经提到的,您不能自己设置“Transfer-Encoding”标头。

    但是,您实际上也不需要使用 HTTP 分块传输编码来将文件增量流式传输到您的服务器并立即开始处理其中的一部分。一个常规的 HTTP POST 可以很好地解决这个问题。即使它是作为单个 HTTP 请求传输的,我相信流式传输/分块的魔法会在 TCP 级别为您发生(如果我在魔法具体发生的地方有误,欢迎其他人纠正我)。我可以确认这是可行的,因为我已经在后端使用 node.js 和 Express 完成了它。我确信它可能也适用于其他服务器端技术。

    HTTP 分块传输编码仅在您不知道要提前发送的流的大小(例如实时视频、视频电话会议、远程桌面会话、聊天等)时才有用。对于这些情况,WebSockets 是解决相同问题的更广泛部署的解决方案: https://developer.mozilla.org/en-US/docs/Web/API/WebSockets_API

    对于您的用例,如果您事先知道文件的大小,您最好坚持使用 XmlHttpRequest 并放弃分块传输编码。或者,您可以尝试使用新的 Fetch API:
    https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-06-30
      • 2018-04-04
      • 1970-01-01
      • 1970-01-01
      • 2011-03-27
      • 2023-03-16
      • 2017-07-08
      • 1970-01-01
      相关资源
      最近更新 更多