在JavaScript中通过HTTP发送二进制数据

40

我试图向我的网络设备发送HTTP POST请求。 我想向设备发送四个特定字节的数据,但不幸的是我似乎只能发送字符串到设备。是否有办法使用JavaScript发送原始二进制数据?

这是我用于进行POST的脚本,除非我在数据字段中放入一个字符串,否则它目前无法运行。有什么想法吗?

(function ($) {
   $.ajax({
      url: '<IP of Address>',
      type: 'POST',
      contentType: 'application/octet-stream',

      //data:'253,0,128,1',
      data:0xFD008001,

      crossDomain: true
   });
})(jQuery);
4个回答

54

默认情况下,jQuery对传递给data属性的数据进行序列化 - 这意味着0xFD008001数字会作为'4244668417'字符串(10个字节,而不是4个)传递到服务器,这就是服务器无法按预期处理它的原因。

通过将$.ajax属性processData设置为false,可以防止这种行为:

默认情况下,传递给数据选项的数据作为对象(技术上任何非字符串类型的数据)将被处理和转换为查询字符串,以适应默认的内容类型“application/x-www-form-urlencoded”。如果您想发送DOM文档或其他未经处理的数据,请将此选项设置为false。

...但这只是整个故事的一部分:XMLHttpRequest.send实现具有自己的限制。 所以我认为你最好的选择是使用TypedArrays制作自己的序列化程序:

// Since we deal with Firefox and Chrome only 
var bytesToSend = [253, 0, 128, 1],
    bytesArray = new Uint8Array(bytesToSend);

$.ajax({
   url: '%your_service_url%',
   type: 'POST',
   contentType: 'application/octet-stream',  
   data: bytesArray,
   processData: false
});

或者完全不使用jQuery:

var bytesToSend = [253, 0, 128, 1],
    bytesArray = new Uint8Array(bytesToSend);

var xhr = new XMLHttpRequest();
xhr.open('POST', '%your_service_url%');
xhr.setRequestHeader('Content-Type', 'application/octet-stream');
xhr.send(bytesArray);

1
我收到了 ArrayBuffer在XMLHttpRequest.send()中已被弃用。请改用ArrayBufferView。 但是接着又收到了一个 ReferenceError: ArrayBufferView未定义 - Musa
是的,我已经重写了这个代码,不再使用ArrayBuffertypedArray实际上作为xhr.send参数被Chrome和Firefox支持。 - raina77ow
谢谢!我对JavaScript还很陌生,所以一直在想是否有简单的东西我忽略了。你的解释绝对超出了我的期望。感谢! - user2984509
你不需要使用循环。类型化数组构造函数接受类似数组的对象,并为您执行循环。所以只需 var bytesArray = new Uint8Array(bytesToSend); 就足够了。详情请见,但我不想单方面进行编辑。 - T.J. Crowder
我理解你的观点,但是浏览器支持怎么办?我假设使用new TypedArray(plainArray)结构只有在支持TypedArray.from(plainArray)的浏览器中才可能进行,而根据这个文档页面的描述,IE和Safari并不允许。 - raina77ow
啊,刚注意到原始的代码(使用ArrayBufferView作为xhr.send参数)只适用于Firefox和Chrome...而且,惊喜的是,到了2016年8月,IE和Safari仍然不支持它。 - raina77ow

8

您可以使用xhr2通过ajax发送二进制数据,您可以将数据发送为类型化数组或Blob

(function ($) {
   var data = new Uint32Array(1);
   data[0] = 0xFD008001; 
   $.ajax({
      url: '<IP of Address>',
      type: 'POST',
      contentType: false,
      processData: false,
      //data:'253,0,128,1',
      data:data,

      crossDomain: true
   });
})(jQuery);

https://developer.mozilla.org/en-US/docs/Web/API/Uint32Array


+1,但实际上这会以相反的顺序发送字节。 - raina77ow
我并没有将其视为字节序列,而是视为u32整数。 - Musa

1
您可以将类型为ArrayBuffer的数据转换为ArrayBufferView,方法如下:

var fileContent = new DataView(<ArrayBuffer_data>);

使用此方法,当发送文件内容时,您将不会在控制台中收到警告。

0
你可以使用atob()btoa():
var data = new Uint32Array(1);
data[0] = 0xFD008001;
atob(data)

这将把您的二进制数据转换成一个可以作为文本发送的base64字符串。


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