Anirban Acharya Anirban Acharya - 2 months ago 26
Javascript Question

sending large files using tcp in node.js but receiving corrupt file

I am trying to write a my own file sharer app using node.js. I wrote the sender code and the receiver code. Things work when sending text files, but fails on attempts of sending files like .jpg or .mp3. The problem is on the receiving end the file is received as "corrupt". Below is my sender code and receiver code

Sender:



const net = require('net');
const fs = require('fs');
var destAddr = process.argv[2],
destPort = process.argv[3],
sourceFile = process.argv[4];
const client = net.connect(destPort, destAddr, function() {
/*fs.readFile(sourceFile,function(err,data){
if(data)
{
if(client.write(data)==true)
{
console.log("Data [ size: %d ] written succesfully",data.length);
client.destroy();
}
else console.log("Data write failure");
}
else
client.write("err");
});
*/
var fileStream = fs.createReadStream(sourceFile);
fileStream.on('error', function(err) {
console.log(err);
});
fileStream.on('open', function() {
fileStream.pipe(client);
});
});





Receiver:



const net = require('net');
const fs = require('fs');
var fileName = 'receivedfile.' + process.argv[2];
// process.argv[2] is the file extension to be used to write the file to disk at the receiving end;
const options = {
allowHalfOpen: false,
pauseOnConnect: false,
};
var fileCount = 0;
const server = net.createServer(options, function(listener) {
listener.on('data', (data) => {
console.log("Data [ size: %d ] received", data.length);
fs.writeFile(fileName, data, function(err) {
if (err) console.log("Error writing file to disk");
else {
console.log("Write successful");
fileCount++;
console.log("[ Files received =] %d", fileCount);
console.log("Press Ctr+c to exit");
}
});
});
}).listen(8001, () => {
console.log("Client is waiting for the file on port 8001");
});





Where am I going wrong?

Answer

The data event can be triggered multiple times during the lifetime of a connection, with various-sized chunks of data.

Instead, it might be easier to use streams:

const server = net.createServer(listener => {
  let stream = fs.createWriteStream(fileName);

  listener.on('error', err => console.log('socket error', err));
  stream  .on('error', err => console.log('file error', err));

  listener.pipe(stream).on('finish', () => {
    console.log("Write successful");
    fileCount++;
    console.log("[ Files received =] %d", fileCount);
    console.log("Press Ctr+c to exit");
  })
}).listen(...);