Reputation: 408
I want to send binary data from a html page to my server via JavaScript, but the server received not the same bytes. The received bytes seems to be converted to a unicode string, see the following example:
xhr.open('POST', '/check', true);
xhr.setRequestHeader('cache-control', 'no-cache');
xhr.setRequestHeader('Content-Type', 'application/octet-stream');
xhr.send('\x41\xFE\x80');
The server should receive 'Aþ€' but it get A├¥┬Ç
.
I tested a lot of things like:
//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');
On server side I run plackup (http://localhost:5000/index.html), and $env->{'CONTENT_LENGTH'}
is 5, so the server really seems to get the 5 bytes A݀
.
Any hint how to receive the original binary data would be great.
Upvotes: 4
Views: 3703
Reputation: 198324
IMHO my Javascript is correct
It is not. As I hinted in a comment, use Uint8Array
, not strings, for binary data:
xhr.send(new Uint8Array([0x41, 0xFE, 0x80]));
If you already have a string... this should work:
xhr.send(new Uint8Array(Array.from('\x41\xFE\x80').map(x => x.charCodeAt(0)))
The explanation: The spec for send
says:
If
body
is aDocument
, then set request body tobody
, serialized, converted to Unicode, and UTF-8 encoded.Otherwise, set request body and
extractedContentType
to the result of extractingbody
.
String
is not a Document
, therefore the first option does not apply. The definition of "extracting" is found in the fetch
spec:
USVString:
Set
action
to an action that runs UTF-8 encode onobject
.Set
Content-Type
totext/plain;charset=UTF-8
.Set
source
toobject
.
And you can see how UTF-8 encoding of your string looks like:
new TextEncoder().encode('\x41\xFE\x80')
// => Uint8Array(5) [65, 195, 190, 194, 128]
Upvotes: 2