16

我有一个通过 HTTP Post 接受音频文件的 REST API。该 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 分块?

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

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

4

2 回答 2

2

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

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

  • 接受字符集
  • 接受编码
  • 访问控制请求标头
  • 访问控制请求方法
  • 联系
  • 内容长度
  • 曲奇饼
  • 饼干2
  • 日期
  • DNT
  • 预计
  • 主持人
  • 活着
  • 起源
  • 推荐人
  • TE
  • 预告片
  • 传输编码
  • 升级
  • 用户代理
  • 通过

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

于 2015-11-03T03:07:10.853 回答
0

正如其他回复已经提到的那样,您不允许自己设置“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

于 2021-11-17T20:56:47.813 回答