如何在纯JavaScript中发送二进制数据?

4
我想通过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├¥┬Ç

有没有什么提示可以帮助我接收原始二进制数据呢?


MDN:发送和接收二进制数据,特别是发送类型化数组作为二进制数据。 - Amadan
是的,我知道这个示例并使用过它。在我看来,我的Javascript是正确的,也许是服务器上的脚本导致了这个错误... - Codr
1个回答

2

在我看来,我的JavaScript是正确的

实际上不是这样的。正如我在评论中暗示的那样,对于二进制数据,请使用Uint8Array而不是字符串:

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

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

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

解释:根据send方法的规范,如果请求体是一个文档,则将请求体设置为序列化后的文档,并转换为Unicode和UTF-8编码。否则,将请求体和extractedContentType设置为提取body的结果。由于字符串不是文档,因此第一个选项不适用。 "提取"的定义在fetch规范中找到。并且您可以看到您的字符串的UTF-8编码如何看起来:
new TextEncoder().encode('\x41\xFE\x80')
// => Uint8Array(5) [65, 195, 190, 194, 128]

可以了!谢谢!但是为什么Adelin的解决方案不起作用呢? - Codr
我对此进行了评论。Blob只是对任意内容的抽象,因此他并没有做任何与你有本质区别的事情:最终,传输的仍然是一个字符串。不要使用字符串来处理二进制数据。 - Amadan
但我在sendAsBinary上发现:send()方法现在支持二进制数据,应该使用它。那么*send()*也应该可以工作了吧!? - Codr
@Codr:从你的链接中可以看到:“警告:此方法已过时,不应使用。相反,您应该直接使用send()方法,该方法现在支持以各种形式发送二进制数据。”而且send()确实有效-我在我的答案中刚刚演示了它。 - Amadan
我使用的 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) - Amadan

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接