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

Posted

技术标签:

【中文标题】通过 HTTP 在 javascript 中发送二进制数据【英文标题】:Sending binary data in javascript over HTTP 【发布时间】:2013-11-26 08:47:55 【问题描述】:

我正在尝试向我网络上的设备发送 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);

【问题讨论】:

【参考方案1】:

您可以像这样将 ArrayBuffer 类型的数据转换为 ArrayBufferView:

var fileContent = new DataView(&lt;ArrayBuffer_data&gt;);

这样,您在发送文件内容时不会在控制台中收到警告。

【讨论】:

【参考方案2】:

您可以使用atob()btoa()

var data = new Uint32Array(1);
data[0] = 0xFD008001;
atob(data)

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

【讨论】:

【参考方案3】:

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

有必要通过将$.ajax 属性processData 设置为false 来防止此类行为:

默认情况下,数据作为对象传入 data 选项 (从技术上讲,除字符串之外的任何内容)将被处理并 转换为查询字符串,适合默认的内容类型 “应用程序/x-www-form-urlencoded”。如果你想发送一个 DOMDocument 或其他未处理的数据,将此选项设置为 false。

...但这只是整个故事的一部分:XMLHttpRequest.send 实现有自己的restrictions。这就是为什么我认为你最好的选择是使用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);

【讨论】:

我得到了ArrayBuffer is deprecated in XMLHttpRequest.send(). Use ArrayBufferView instead.,然后得到了ReferenceError: ArrayBufferView is not defined 是的,我已将其重写为不使用ArrayBuffer; typedArray 实际上被 Chrome 和 Firefox 支持为 xhr.send 参数。 谢谢!我对 javascript 很陌生,所以我想我缺少一些简单的东西。你的解释肯定超越了。谢谢! 上面不需要你的循环。类型化数组构造函数接受类似数组的对象并为您执行循环。因此,您只需要var bytesArray = new Uint8Array(bytesToSend);。 Details here,但我不想单方面编辑它。 我明白你的意思,但是浏览器支持呢?我假设使用new TypedArray(plainArray) 构造只能在支持TypedArray.from(plainArray) 的浏览器中使用,而从this docpage 来看,IE 和Safari 不允许这样做。【参考方案4】:

您可以使用 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,但这实际上以相反的顺序发送字节。 ) 好吧,我并没有把它看作一个字节序列,而是一个 u32 int。

以上是关于通过 HTTP 在 javascript 中发送二进制数据的主要内容,如果未能解决你的问题,请参考以下文章

无法通过XMLHttpRequest发送大型json数据--javascript

如何通过分析 JavaScript & HTML 来检测 HTTP 请求?

通过 XML HTTP 请求发布发送密码(启用 HTTPS)

如何发送带有标头参数的 HTTP 请求?

JAVA通过HttpClient发送HTTP请求的方法

在php中手动创建一个HTTP Response对象,发送,用Javascript捕获