Sending images to the client with nodejs and socket.io - javascript

with the following code I'm able to send an Image to the client with socket.io, but I want also to send the size as a second argument. I would like to understand why the argument "size" is getting always undefined when I try to pass it to the socket.emit function. socket.emit('firstChunkSent', data, size). Can you pls fix it ?
var io = require('../server').io
io.sockets.on('connection', function (socket) {
socket.on('imageRequest', function () {
getTheNewImage(function(data,size){
socket.emit('firstChunkSent', data, size)
});
});
});
function getTheNewImage(callback){
var filename = 'image.gif';
var base64FileSize = fs.stat(filename,function(err,stats){
if (err) { throw err; }
return stats.size
});
var readable = fs.createReadStream(filename, { encoding: 'base64' });
readable.on('readable', function() {
var getImageData = function(){
while (null !== (base64ImageData = readable.read())) {
return base64ImageData
}
}
callback(getImageData(),base64FileSize)
});
readable.on('end', function() {
console.log('there will be no more data.')
});
readable.on('error', function(err) {
console.log('here is the error: '+err)
readable.end(err);
});

return stats.size
Need to use the callback
function getTheNewImage(callback){
var filename = 'image.gif';
var base64FileSize = fs.stat(filename,function(err,stats){
if (err) return callback(new Error(err));
callback(null, stats.size)
});
getTheNewImage(function(data,size)
First param will be the error, not data

Related

Callback is not a function -manage asynchronous call Node js

I am reading files from ftp using the code below.
var JSFtp = require("jsftp");
var config = require('./config.json');
var FtpService = function () {};
// Connect to FTP
var Ftp = new JSFtp({
host: config.ftp.host,
port: config.ftp.port,
user: config.ftp.user,
pass: config.ftp.pass
});
FtpService.prototype.getFTPDirectoryFiles = function (callback) {
Ftp.list(config.ftp.FilePath, function(err, res) {
if(err){
console.log('File Listing Failed', err);
callback(null,err);
return;
}
else{
console.log(res);
callback(null,res);
}
});
};
FtpService.prototype.closeFtp = function () {
console.log('Disconnect to FTP');
};
module.exports = new FtpService();
Now i include this ftp service js file in my index.js as
var ftp = require('./ftpservice.js');
ftpfiles = ftp.getFTPDirectoryFiles();
console.log(ftpfiles);
getFTPDirectoryFiles returns the list of file. But if i call it via index.js i get undefined ftpfiles. This is because of the asynchronous nature of node js.
so i thought of adding callback but
I am getting the error Callback is not defined in function FtpService.prototype.getFTPDirectoryFiles
In this line:
ftpfiles = ftp.getFTPDirectoryFiles()
you are not passing the callback that that function requires and are trying to use a return value that the function does not return.
You need to do something like this:
var ftp = require('./ftpservice.js');
ftp.getFTPDirectoryFiles(function(err, ftpfiles) {
if (err) {
console.log(err);
} else {
console.log(ftpfiles);
}
});
You need to pass a callbackfunction in your function getFTPDirectoryFiles();
var ftp = require('./ftpservice.js');
var ftpFiles;
function setFtpFiles(err, res) {
if (err) throw err;
ftpFiles = res; // to use "ftpFiles" variable later
console.log(res);
}
ftp.getFTPDirectoryFiles(setFtpFiles);
1 Don't change args order to call callback. (replace callback(null,err); and callback(null,res); by callback(err,res);)
2 You need define a specifc function (your callaback) an give it to ftp.getFTPDirectoryFiles().
var JSFtp = require("jsftp");
var config = require('./config.json');
var FtpService = function () {};
// Connect to FTP
var Ftp = new JSFtp({
host: config.ftp.host,
port: config.ftp.port,
user: config.ftp.user,
pass: config.ftp.pass
});
FtpService.prototype.getFTPDirectoryFiles = function (callback) {
Ftp.list(config.ftp.FilePath, function(err, res) {
if(err){
console.log('File Listing Failed', err);
callback(err, res);
return;
}
else{
console.log(res);
callback(err, res);
}
});
};
FtpService.prototype.getFTPDirectoryFilesSimplify = function (callback) {
// no console.log, but very more simple !
Ftp.list(config.ftp.FilePath, callback);
};
FtpService.prototype.closeFtp = function () {
console.log('Disconnect to FTP');
};
and then :
var ftp = require('./ftpservice.js');
ftpfiles = ftp.getFTPDirectoryFiles(function(err,res){
// do your specifc job here using err and res
});
console.log(ftpfiles);

Getting error can not get header after they send when read files from directory?

I am trying to get the name and created date of the files. In the code below it throws error when I call the api. It is reading the directory and printing all the file names but it's not sending back to callback. Any idea what is implemented wrong?
service.js
var fs = require('fs');
var path = require('path');
var async = require('async');
var currentDate = new Date();
var objToReturn = [];
var logsDirectory = './logs'
function readDirectory(env, callback) {
fs.readdir(logsDirectory + '/' + env, function(err, files) {
// loop through each file
async.eachSeries(files, function(file, done) {
var dirPath = logsDirectory + '/' + env;
var filePath = path.join(dirPath, file);
var fileInfo = {};
fs.stat(filePath, function(err, stats) {
if (err) {
console.info("File doesn't exist");
} else {
fileInfo.fileDate = stats.birthtime;
fileInfo.filename = file;
objToReturn.push(fileInfo);
done();
}
});
});
},
function(err) {
if (err) {
console.info('error', err);
return;
}
// when you're done reading all the files, do something...
console.log('before Callback', objToReturn);
callback(objToReturn);
});
}
exports.readDirectory = readDirectory;
app.js
var stDirectory = require('./app/serverfiles/stDir');
app.get('/getAllFiles',function(req,res){
var env = req.query.env
console.log('printing',env);
stDirectory.readDirectory(env,function(files){
res.json(files);
console.log('Api files',files);
});
});
There are a few issues:
instead of passing the "final" handler to async.eachSeries(), you're passing it to fs.readdir(), so callback will never get called;
you're declaring objToReturn outside of the function, which isn't a good idea because multiple requests could be handled in parallel;
you're not handling any errors properly;
you should really use the Node.js callback idiom of calling callbacks with two arguments, the first being errors (if there are any) and the second being the result of the asynchronous operation.
The code below should fix these issues:
function readDirectory(env, callback) {
let objToReturn = [];
fs.readdir(
logsDirectory + "/" + env,
function(err, files) {
if (err) return callback(err);
// loop through each file
async.eachSeries(files, function(file, done) {
var dirPath = logsDirectory + "/" + env;
var filePath = path.join(dirPath, file);
var fileInfo = {};
fs.stat(filePath, function(err, stats) {
if (err) {
console.info("File doesn't exist");
return done(err);
} else {
fileInfo.fileDate = stats.birthtime;
fileInfo.filename = file;
objToReturn.push(fileInfo);
done();
}
});
}, function(err) {
if (err) {
console.info("error", err);
return callback(err);
}
// when you're done reading all the files, do something...
console.log("before Callback", objToReturn);
callback(null, objToReturn);
}
);
}
// To call it:
stDirectory.readDirectory(env, function(err, files) {
if (err) {
res.sendStatus(500);
} else {
res.json(files);
console.log('Api files',files);
}
});
You should also consider using async.mapSeries() instead of async.eachSeries() and using a separate array (objToReturn).

node can't set headers after they are sent

i know this question asked many time before but still i'm struggling to figure this out. i have a set of js files. first one is index.js
app.all('/backend/*/*', function(req, res){ // backend/product/getProduct
serviceType = req.params[0];
methodType = req.params[1];
exports.serviceType= serviceType;
exports.methodType= methodType;
main.checkService()
});
in here im extracting the params and call checkService method in main.js file
main.js
function checkService(){
switch(index.serviceType){
case 'product':
product.checkMethod();
break;
default :
console.log('no such service')
}
}
then it move to product.js file
function checkMethod(){
var methodName = index.methodType,
res = index.res,
req = index.req;
switch(methodName){
case 'samplePost':
var body = req.body;
proHan.samplePost(body,function(data,msg,status){
sendRes(data,msg,status);
});
break;
default :
console.log('no such method')
}
function sendRes(jsonObj,msg,status){
var resObj = {
status : status,
result : jsonObj,
message : msg
}
res.json(resObj);
}
first it moves to samplePost method in handler.js
once the http req finised executing, callback return the results and call sendRes method and send the json
function samplePost(jsonString,cb){
var res = config.setClient('nodeSample');
// jsonString = JSON.parse(jsonString);
res.byKeyField('name').sendPost(jsonString,function(data,msg,status){
cb(data,msg,status);
});
}
to send http req i written a common file. that is config.js
function setClient(_cls){
var client = new Client(url);
return client;
}
function parentClient(url){
this.postBody = {
"Object":{},
"Parameters":{
"KeyProperty":""
}
};
}
function paramChild(){
parentClient.apply( this, arguments );
this.byKeyField = function(_key){
this.postBody.Parameters.KeyProperty = _key;
return this;
}
}
function Client(url){
parentClient.apply( this, arguments );
this.sendPost = function(_body,cb){
_body = (_body) || {};
this.postBody.Object = _body;
var options = {
host : 'www.sample.com',
port : 3300,
path: '/somrthing',
headers: {
'securityToken' : '123'
}
};
options.method = "POST";
var req = http.request(options, function(response){
var str = ''
response.on('data', function (chunk) {
str += chunk;
});
response.on('end', function () {
cb(JSON.parse('[]'),'success',200)
});
});
//This is the data we are posting, it needs to be a string or a buffer
req.on('error', function(response) {
cb(JSON.parse('[]'),response.errno,response.code)
});
req.write(JSON.stringify(this.postBody));
req.end();
}
}
paramChild.prototype = new parentClient();
Client.prototype = new paramChild();
when i send the first req its work but from then again the server crashes. it seems like i can't call res.end method again in a callback method. how can i fix this. thank you.
you can't call res.end two times. Here is a simple exemple to deal with callback with a basic node server.
const http = require('http');
const hostname = '127.0.0.1';
const port = 4242;
let something = true;
function callback(req, res) {
something = !something;
res.setHeader('Content-Type', 'text/plain');
res.end('Callback Hello World\n');
}
const server = http.createServer((req, res) => {
res.statusCode = 200;
if (something) {
callback(req, res);
} else {
something = !something;
res.setHeader('Content-Type', 'text/plain');
res.end('Hello World\n');
}
});
server.listen(port, hostname, () => {
console.log(`Server running at http://${hostname}:${port}/`);
});

Uploading to dropbox via node js fails

I have the following code to read from a stream and upload to Dropbox. But I'm getting a
Uncaught TypeError: Cannot call method 'toString' of undefined
at Function.Dropbox.Util.Xhr.Xhr.urlEncodeValue (node_modules\dropbox\lib\dropbox.js:3695:40)
at Function.Dropbox.Util.Xhr.Xhr.urlEncode (node_modules\dropbox\lib\dropbox.js:3689:59)
at Xhr.Dropbox.Util.Xhr.Xhr.paramsToUrl (node_modules\dropbox\lib\dropbox.js:3570:40)
at Xhr.Dropbox.Util.Xhr.Xhr.prepare (node_modules\dropbox\lib\dropbox.js:3598:14)
at Client.Dropbox.Client.Client._dispatchXhr (node_modules\dropbox\lib\dropbox.js:2137:11)
at Client.Dropbox.Client.Client.resumableUploadStep (node_modules\dropbox\lib\dropbox.js:1454:19)
.....
error when I try to run the code.If I give a 'false' as cursor, the error doesn't occur in step function, but still it occures in finish function. Can anyone help me on this?
stream.on('data', function (data) {
client.resumableUploadStep(data, function (error, cursor) {
if (error) {
return console.log(error);
}
})
});
stream.on('end', function () {
client.resumableUploadFinish(fileName, function (error, stats) {
if (error) {
return callback(error);
}
return callback(null, stats);
});
});
I used the following code and now it works.
var pcursor = null;
var eventObject = new EventEmitter();
var counter = 0;
stream.on('data', function (data) {
counter++;
client.resumableUploadStep(data, pcursor, function (error, cursor) {
if (error) {
return callback(error);
}
counter--;
pcursor = cursor;
eventObject.emit('event');
});
});
stream.on('end', function () {
eventObject.on('event', function () {
if (counter == 0) {
client.resumableUploadFinish(fileName, pcursor, function (error, stats) {
if (error) {
return callback(error);
}
return callback(null, stats);
});
counter = -1;
}
});
eventObject.emit('event');
});
It looks like you're missing the cursor parameter to resumableUploadFinish. Also, you should be passing in a cursor to resumableUploadStep after the first call too.
I think the code you want is something like this (completely untested):
var cursor = null;
stream.on('data', function (data) {
client.resumableUploadStep(data, cursor, function (error, new_cursor) {
cursor = new_cursor;
});
});
stream.on('end', function () {
client.resumableUploadFinish(fileName, cursor, function (error, stats) {
return callback(null, stats);
});
});

node.js and async module error

I am getting an undefined variable in my code and not sure what the error in my code is:
I get client as undefined when I call getClient...
I have a soap client creation singleton and I have:
var mySingleton = (function() {
var soap = require('soap');
var async = require('async');
var instance;
var client;
function init() {
var url = "http://172.31.19.39/MgmtServer.wsdl";
var endPoint = "https://172.31.19.39:9088";
var options = {};
options.endpoint = endPoint;
async.series([
function(callback) {
soap.createClient(url, options, function (err, result){
console.log('Client is ready');
client = result;
client.setSecurity(new soap.BasicAuthSecurity('admin-priv', 'password'));
callback();
});
}
],
function(err) {
if (err)
return next(err);
});
return {
getClient : function() {
console.log("I will give you the client");
**return client;**
},
publicProperty : "I am also public",
};
};
return {
getInstance : function() {
if (!instance) {
instance = init();
}
return instance;
}
};
})();
module.exports = mySingleton;
so my consumer is :
var soapC = mySingleton.getInstance();
var mySoapClient = soapC.getClient();
I get mySingleton.client is undefined.
Why?
Sure there are better solutions than this one, but it shows you that it can be implemented easier (without async, without singleton):
var soap = require('soap');
var client;
var url = "http://172.31.19.39/MgmtServer.wsdl";
var options = {
endpoint: "https://172.31.19.39:9088"
};
module.exports = {
getClient: function (callback) {
if (client) {
callback(null, client);
return;
}
soap.createClient(url, options, function (err, result) {
if (err) {
callback(err);
return;
}
console.log('Client is ready');
client = result;
client.setSecurity(new soap.BasicAuthSecurity('admin-priv', 'password'));
callback(null, client);
});
},
publicProperty: "I am also public"
};
And when using the client:
// using the client
var mySoapServer = require('./path/to/above/code.js');
mySoapServer.getClient(function (err, client) {
if (err) { /* to error handling and return */ }
client.someRequestMethod(myEnvelope, function (err, response) {
// ...
});
});
There might be a problem when your Soap-Clients gets into trouble (there is no logic to reconnect in case of error). For this you could have a look at the source code of Redis-Client, MySQL-Client, MongoDB-Client, ...
Edit
Some comments on the different aproaches:
The Singleton-pattern is not needed here. Node will execute this JS file only once and further requires get only a reference to the exports. There is no need to create an IIFE scope - the variables won't be visible outside, only the exports.
Programming in Node.js is (besides some special cases) an all-async way. If not done consequently, it just doesn't work or fails/succeeds only if you have good/bad luck.
Error handling looks very much like a lot of boilerplate, but it's necessary in most cases.

Categories