Sending binary data in javascript over HTTP
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.
Admin
Updated on November 12, 2020Comments
-
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 over 10 years+1, but this actually sends the bytes in the reverse order. )
-
Musa over 10 yearsI get
ArrayBuffer is deprecated in XMLHttpRequest.send(). Use ArrayBufferView instead.
but then get aReferenceError: ArrayBufferView is not defined
-
Musa over 10 yearsWell I wasn't thinking of it as a sequence of bytes but as a u32 int.
-
raina77ow over 10 yearsYes, I've rewritten this to not use
ArrayBuffer
; typedArray are actually supported both by Chrome and Firefox asxhr.send
param. -
Admin over 10 yearsThanks 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 almost 8 yearsThere'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 almost 8 yearsI see your point, but what about browser support? I've assumed using
new TypedArray(plainArray)
construct is only possible in the browsers that supportTypedArray.from(plainArray)
, and judging from this docpage, IE and Safari don't allow that. -
raina77ow almost 8 yearsAh, just noticed the original recipe (using
ArrayBufferView
asxhr.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.