Sending binary data in javascript over HTTP

75,107

Solution 1

By default, jQuery serializes the data (passed in data property) - and it means 0xFD008001 number gets passed to the server as '4244668417' string (10 bytes, not 4), that's why the server treats it not as expected.

It's necessary to prevent such behaviour by setting $.ajax property processData to false:

By default, data passed in to the data option as an object (technically, anything other than a string) will be processed and transformed into a query string, fitting to the default content-type "application/x-www-form-urlencoded". If you want to send a DOMDocument, or other non-processed data, set this option to false.

... but that's only part of the whole story: XMLHttpRequest.send implementation has its own restrictions. That's why your best bet, I suppose, is to make your own serializer using 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
});

Or without using jQuery at all:

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);

Solution 2

You can send binary data via ajax with xhr2, you can send the data as a typed array or a 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

Solution 3

You can convert your data with type of ArrayBuffer to a ArrayBufferView like this:

var fileContent = new DataView(<ArrayBuffer_data>);

With this you wont get a warning in the console when sending fileContent.

Share:
75,107
Admin
Author by

Admin

Updated on November 12, 2020

Comments

  • Admin
    Admin over 3 years

    I'm trying to send a HTTP POST to a device on my network. I want to send four specific bytes of data to the device unfortunately I only seem to be able to send strings to the device. Is there anyway to send raw binary using javascript?

    Here's the script I'm using to do the POST, it currently doesn't run unless I put a string in the data field. Any ideas?

    (function ($) {
       $.ajax({
          url: '<IP of Address>',
          type: 'POST',
          contentType: 'application/octet-stream',
    
          //data:'253,0,128,1',
          data:0xFD008001,
    
          crossDomain: true
       });
    })(jQuery);
    
  • raina77ow
    raina77ow over 10 years
    +1, but this actually sends the bytes in the reverse order. )
  • Musa
    Musa over 10 years
    I get ArrayBuffer is deprecated in XMLHttpRequest.send(). Use ArrayBufferView instead. but then get a ReferenceError: ArrayBufferView is not defined
  • Musa
    Musa over 10 years
    Well I wasn't thinking of it as a sequence of bytes but as a u32 int.
  • raina77ow
    raina77ow over 10 years
    Yes, I've rewritten this to not use ArrayBuffer; typedArray are actually supported both by Chrome and Firefox as xhr.send param.
  • Admin
    Admin over 10 years
    Thanks for this! I'm quite new to javascript so I was thinking there was something simple I was missing. Your explanation definitely went above and beyond. Thanks!
  • T.J. Crowder
    T.J. Crowder almost 8 years
    There's no need for your loops above. The typed array constructors accept array-like objects and do the loop for you. So just var bytesArray = new Uint8Array(bytesToSend); is all you need. Details here, but I didn't want to edit that in unilaterally.
  • raina77ow
    raina77ow almost 8 years
    I see your point, but what about browser support? I've assumed using new TypedArray(plainArray) construct is only possible in the browsers that support TypedArray.from(plainArray), and judging from this docpage, IE and Safari don't allow that.
  • raina77ow
    raina77ow almost 8 years
    Ah, just noticed the original recipe (using ArrayBufferView as xhr.send param) was only for Firefox and Chrome... And, surprise, surprise, it looks like it's the same thing in Aug'16, IE and Safari still don't support that.