首页 > 解决方案 > 如何在纯 JavaScript 中发送二进制数据?

问题描述

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

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

标签: javascriptajaxunicodebinary

解决方案


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

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

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

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

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

解释:规范send说:

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

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

String不是 a Document,因此第一个选项不适用。“提取”的定义可在fetch规范中找到:

USV字符串:

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

设置Content-Typetext/plain;charset=UTF-8

设置sourceobject

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

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

推荐阅读