How to send ArrayBuffer in json from js client to nodejs server? - javascript

I am trying to send data of type ArrayBuffer in json to my server using socket.io like this:
socket.emit('record', {
name: myUsername + '.wav',
data: data //arraybuffer
});
On server side, when i receive 'record' event in socket, I get the data from JSON and save it in name file like this:
socket.on('record', function(message){
var fileWriter = new wav.FileWriter(message.name, {
channels: 1,
sampleRate: 48000,
bitDepth: 16
});
message.data.pipe(fileWriter);
});
I am using require('wav') & require('stream') package from npm. The problem is that my server crashes on message.data.pipe(fileWriter); with this error:
TypeError: message.data.pipe is not a function
What am I doing wrong? Can't i send ArrayBuffer like this in socket.io?

data is an ArrayBuffer, not a ReadableStream. Enqueue data to be read by a ReadableStream, passed to a WritableStream or TransformStream, for example using .pipeThrough(), see Receiving data via stdin and storing as a variable/array.

Related

Problems with Blob acquisition when receiving data through a web-socket

In the process of communicating with the server using a web socket, the data is handed over to the server to Json.
And in the process of receiving data through onmessage, the data came into Blob, not Json or string.
I couldn't find a way to change this Blob to Json, so I posted a question here.
Is there any way to receive the data in string or Json?
Or how to change Blob to string or Json.
The server is written in c++ and sent as a string.
useEffect(() => {
//var socket = new WebSocket("ws://172.30.1.50:65432/websocket");
const socket = new WebSocket("ws://ip:port/websocket"); //For convenience, I wrote down ip and port.
socket.Type = "blob"
socket.onopen = function (event) {
socket.send(JSON.stringify({ 'CMD': 'test' }))
console.log("connetion?");}
socket.close
socket.onmessage = function (event) {
console.log((event.data))
}, []})
The WebSocket protocol supports two kinds of data messages: text and binary. When a text message is received by Javascript, it is deserialised as a string; when a binary message is received, it is deserialised as either an ArrayBuffer or a Blob, depending on the value of the websocket's binaryType property (the default is to return a Blob).
The fact that you got a Blob indicates that the server sent a binary message. This is unusual for a JSON message, so either the server is very unusual, or the protocol is not based on JSON.
In any case, you can convert r data into a string by calling the async .text() method:
let data = await event.data.text();
If the contents is indeed JSON, then you may parse it as usual:
let value = JSON.parse(data);

Sending an image/video using sockets and node

My application requires a section for users to communicate each other. For this, I am using socket-io. For sending text(as strings). I use utf-8, which works perfectly.
However, when sending an image or a video on a socket, how do I approach this? Would I turn the image or the video into binary format, and send that on the socket?
Yes there is an example about how to send your files with socket.io :
var fileReader = new FileReader(),
slice = file.slice(0, 100000);
fileReader.readAsArrayBuffer(slice);
fileReader.onload = (evt) => {
var arrayBuffer = fileReader.result;
socket.emit('slice upload', {
name: file.name,
type: file.type,
size: file.size,
data: arrayBuffer
});
}
there is a full tutorial with example about send file with socket.io and receive it in the server nodeJs follow this

Node.js [net library]: How to make the buffer object a string?

I am fairly new to Node.js, and I am creating a TCP client that sends and receives data from a certain server.
My problem is with the "data" event emitted when data is received through the socket.
client.on('data', function(data) {
console.log('[TCP] Client received: ' + data); // Logs the message as it is supposed to be.
console.log(data.split(" ")); // Does not work because it says that data is not a string
});
I tried toString(data) but it did not output it as it was logged by the console.
So my question is: How can I convert this object to a string as it is logged in the console?
Thank you for your input :)
if data is a Buffer instance as it looks like, it's
client.on('data', function(data) {
console.log(data.toString('utf8'));
})

EDITED: Can't send POST request to Express server with Fetch API, keep getting JSON.parse error

I'm new to JavaScript, and am learning to develop with an Express server on Glitch.com. I am running into issues with my Fetch API POST request, where it keeps returning a JSON.parse error when I try to send it a JSON object.
SyntaxError: JSON.parse: unexpected character at line 1 column 1 of the JSON data
I plan on using the JSON object to take in input from an HTML form, and I have that data saved in string variables but cannot use it. When I test JSON.stringify and JSON.parse in the console, it logs it as
Object { some: 1 }
I am also not sure where I should be directing the URL of the Fetch API, though the Express code is saved in a folder in Glitch called "server/ex.js". Thank you in advance!
UPDATE
So it looks like I'm getting errors with my Express server, when I check the response status code it's 404. How do I find the right URL?
try this code:
var payload = {
a: 1,
b: 2
};
var data = new FormData();
data.append( "json", JSON.stringify( payload ) );
fetch("/echo/json/",
{
method: "POST",
body: data
})
.then(function(res){ return res.json(); })
.then(function(data){ alert( JSON.stringify( data ) ) })
This code above is in: Fetch: POST json data
If you started a node project, you will want to edit the server.js file to include the following codes:
app.post('/server/ex.js',function(req,res){
res.send(JSON.stringify({
'hello':'world'
}))
})
then the fetch request in client.js should return the json object
edit1) sorry, just realised it was a post request, not a get request
edit2) in order to parse the json object you sent {some:1}, you will need bodyparser package.
edit after seeing server.js:
you will need the following for server.js at the very top if it does not already:
var express = require('express')
var app = express()
in addition, it will need the code snippit above somewhere later.
I am not too sure where you are getting the next() function from, though.

how to route different data types over Websockets?

I have to send a lot of ArrayBuffers (audio voice data) over a websocket server. The Problem is, that the client has to know which type of ArrayBuffer the incoming data is (Uint8 / Uint16 / Float32...). The type can change on the fly if the user switch to an other audio quality.
What is the best way to inform the client about the array type ?
Ideas so far:
Put an extra prefix byte to the array (this might be slow because i have to create a new arrayBuffer for each audio chunk)
Using different routes like /16float or /uint8 to know which data is coming. (I have not found any information how this is done with websockets)
Is there an better way to do this? Can anyone give me an example how URL-Path routes with websockets work ?
EDIT:
I implemented prefix bytes to send information about client and array type, but still interested in better/other solutions.
Cracker0dks, why are you using pure websockets and not a library. With primus you can use substream - namespace - which is more or less exactly what you want - you can also use binnary parser with primus.
Socket.io is also an option but they are not as good as primus.(in my opinion)
Currently its the most supported/ stable / complete solution for ws
// server side:
var primus
, server
, substream
, http
, Uint8
, Uint16
, Float32
;
Primus = require('primus');
http = require('http');
substream = require('substream');
server = http.createServer();
primus = new Primus(server);
primus.use('substream', substream);
server.listen(8000);
primus.on('connection', function (spark) {
Uint8 = spark.substream('Uint8');
Uint16 = spark.substream('Uint16');
Float32 = spark.substream('Float32');
Uint8.on('data', function (data) {
console.log(data); //we recieve data from client on Uint8 ('to server')
});
Uint16.on('data', function (data) {
console.log(data); //we recieve data from client on Uint16 ('to server')
});
Float32.on('data', function (data) {
console.log(data); //we recieve data from client on Float32 ('to server')
});
Uint8.write('to client'); // write data to client to Uint8
Uint16.write('to client'); // write data to client to Uint16
Float32.write('to client'); // write data to client to Float32
//
// piping data to Float32
//
fs.createReadSteam(__dirname + '/example.js').pipe(Float32, {
end: false
});
//
// To stop receiving data, simply end the substream:
//
Uint16.end();
});
// client side:
var primus
, Uint8
, Uint16
, Float32
;
primus = new Primus('server address');
Uint8 = primus.substream('Uint8');
Uint8.write('to server'); // write data to server to Uint8
Uint16 = primus.substream('Uint16');
Uint16.write('to server'); // write data to server to Uint16
Float32 = primus.substream('Float32');
Float32.write('to server'); // write data to server to Float32
Uint8.on('data', function (data) {
console.log(data); // you get data from server to Uint8 ('to client')
});
Uint16.on('data', function (data) {
console.log(data); // you get data from server to Uint8 ('to client')
});
Float32.on('data', function (data) {
console.log(data); // you get data from server to Uint8 ('to client')
});
The above was taken from their documentation and changed to fit your example - i did not test it but it should work.
I hope that help.

Categories

Resources