【问题标题】:How to send binary data in pure JavaScript?如何在纯 JavaScript 中发送二进制数据?
【发布时间】:2019-07-18 19:33:27
【问题描述】:

我想通过 JavaScript 将二进制数据从 html 页面发送到我的服务器,但服务器收到的字节不同。接收到的字节似乎被转换为 unicode 字符串,请参见以下示例:

xhr.open('POST', '/check', true);
xhr.setRequestHeader('cache-control', 'no-cache');
xhr.setRequestHeader('Content-Type', 'application/octet-stream');
xhr.send('\x41\xFE\x80');

服务器应该收到“Aþ€”,但它得到了A├¥┬Ç。

我测试了很多东西,比如:

//xhr.overrideMimeType('text/plain; charset=iso-8859-1');
//xhr.setRequestHeader('Content-type', 'text/plain; charset=iso-8859-1');
//xhr.setRequestHeader('Content-type', 'application/xml; charset=UTF-8');
//xhr.overrideMimeType('text/plain; charset=x-user-defined');
//xhr.overrideMimeType('text\/plain; charset=x-user-defined');

在服务器端我运行 plackup (http://localhost:5000/index.html),$env->{'CONTENT_LENGTH'} 是 5,所以服务器似乎真的得到了 5 个字节 A├¥┬Ç。

任何提示如何接收原始二进制数据都会很棒。

【问题讨论】:

标签: javascript ajax unicode binary


【解决方案1】:

恕我直言,我的 Javascript 是正确的

事实并非如此。正如我在评论中所暗示的,对二进制数据使用Uint8Array,而不是字符串:

xhr.send(new Uint8Array([0x41, 0xFE, 0x80]));

如果你已经有一个字符串......这应该可以工作:

xhr.send(new Uint8Array(Array.from('\x41\xFE\x80').map(x => x.charCodeAt(0)))

解释:spec for send 说:

如果body 是Document,则将请求正文设置为body、序列化、转换为Unicode 和UTF-8 编码。

否则,将请求正文和extractedContentType设置为提取body的结果。

String 不是Document,因此第一个选项不适用。 “提取”的定义见fetch spec:

USVString:

将action 设置为在object 上运行UTF-8 编码的操作。

将Content-Type 设置为text/plain;charset=UTF-8。

将source 设置为object。

你可以看到你的字符串的 UTF-8 编码是怎样的:

new TextEncoder().encode('\x41\xFE\x80')
// => Uint8Array(5) [65, 195, 190, 194, 128]

【讨论】:

  • 有效!谢谢!但为什么 Adelin 的解决方案不起作用?
  • 我对此发表了评论。 Blob 只是对任意内容的抽象,因此他所做的事情与您没有本质上的不同:最终,它仍然是一个被传输的字符串。不要将字符串用于二进制数据。
  • 但我在sendAsBinary 上发现:send() 方法现在支持二进制数据,现在应该使用它。所以 send() 也应该可以工作!?
  • @Codr:来自您的链接:“警告:此方法已过时,不应使用。您应该简单地使用 send() 方法,该方法现在支持各种形式的二进制数据。” send() 确实有效 - 我刚刚在我的回答中演示了它。
  • Uint8Array(我用的那个)是ArrayBufferView的一种。同样,Blob 只是一个容器,其行为与您初始化它的任何数据源一样:如果您使用 5 字节字符串对其进行初始化,它将像字符串一样发送 5 个字节。检查这个:var blob = new Blob(['\x41\xFE\x80'], {type: 'application/octet-stream'}); var reader = new FileReader(); reader.addEventListener("loadend", () => console.log(reader.result)); reader.readAsArrayBuffer(blob).
猜你喜欢
  • 2013-11-26
  • 2015-10-24
  • 1970-01-01
  • 1970-01-01
  • 2012-09-10
  • 2023-03-12
  • 1970-01-01
  • 2016-03-07
相关资源
最近更新 更多