How to get base64 value from function? - node.js

I need to create dummy data for mongodb, part of the data is pictures which needs to be converted first to base64 and then i need the display them.
Here is my controller
var buffer = require('buffer');
var path = require('path');
var fs = require('fs');
var users_model;
var PageUsersController = function () {
users_model = require('../models/users_model');
}
module.exports = PageUsersController;
var pic_binary;
function encode_base64(filename){
fs.readFile(path.join(__dirname,'../foo/',filename),function(error,data){
if(error){
throw error;
}else{
var buf = Buffer.from(data);
var base64 = buf.toString('base64');
pic_binary = base64;
console.log(pic_binary); // returns result.
return base64;
}
});
}
encode_base64('user_pic.jpg');
PageUsersController.getUserDetails = function (cb) {
var flat_details = [
{
user_name: "john",
user_pic:pic_binary, // always return undefined
}
];
return cb(null, flat_details);
}
How can i pass the mongodb schema the variable 'pic_binary' that holds the results of the encoding?
I've tried to set the function's value into a variable and then passing it... but i get undefined no matter how i'm setting the result as variable

Got it.
Should have used Synchronized :
var buff = fs.readFileSync(path.join(__dirname,'../user_pic/','profile_pic.png'));
var base64data = buff.toString('base64');
var flat_details = [
{
user_pic:base64data , // problem solved.
}
];

Related

Not able to access value in nodejs code

I have following code in my nodejs function. Even if the IF condition is true, I am not getting values updated for stringResponse variable.
var fs = require('fs'),
byline = require('byline');
var stream = fs.createReadStream('Solutionbank.csv');
var stringResponse = "We found a similar issue. ";
stream = byline.createStream(stream);
stream.on('data', function(line) {
var csvLine = line.toString('utf8');
csvLine = csvLine.toLowerCase().trim();
var msgText = subject.toLowerCase().trim();
//console.log("email block",msgText);
if(csvLine.indexOf(msgText) > -1) {
var arr = line.toString('utf8').split(",");
stringResponse = stringResponse + "Issue ID"+arr[0]+",Subject : "+arr[1]+", Resolution Comment:"+arr[2];
console.log(stringResponse);
}
});
console.log("stringResponse from email",stringResponse);
Line :
console.log("stringResponse from email",stringResponse);
Is outsite on('data') callback function, this line is called before setting the stringResponse variable. Put it at the end of the callback function (inside). Or in the other callback function called at the end of the stream :
stream.on('data', function(line) {
...
console.log("stringResponse from email",stringResponse); // show each append
});
stream.on('end', function() {
...
console.log("stringResponse from email",stringResponse); // show each append
});

Variable precedence (global in node js?)

"use strict";
var Tabletop = require("tabletop");
var base64 = require('base-64');
Tabletop.init( { key: 'xxxxxg46hgfjd',
callback: showInfo,
simpleSheet: true } )
function showInfo(data, tabletop) {
console.log(data);
console.log(base64.encode(data));
}
var vGlobals = {
dataString: base64.encode(data)
};
module.exports = vGlobals;
How can I access the data variable from showInfo, to use in vGlobals? It says that it hasn't been defined.
Your approach is wrong, you can't do it this way because TableTop call your callback asynchronously.
My suggestion (a quick one) :
var dataString = null;
module.exports = function(cb) {
if (dataString == null)
Tabletop.init({
key: 'xxxxxg46hgfjd',
callback: function(data, tabletop) {
dataString = base64.encode(data);
cb(dataString);
},
simpleSheet: true
});
else cb(dataString);
};
And to get the data :
var dataManager = require('./myfile');
dataManager(function(dataString) {
//here is your data do what you want with it
})
You should look/learn more about node/javascript and asynchronous/event-driven programing.

mocha test sends `test` as variable to node app

When writing the tests for my entry file, index.js I run into the problem that the command mocha test passes test as an argument to index.js as it uses process.argv to receive parameters to run on a development environment. I had thought that by using something like minimist to name the parameters would fix this, however this problem still remains when running the tests. In this way my tests do not use the object provided in my test suits, as shown in the following code.
How do I get around this, so that when running my tests, it uses the event object I provide in my test set-up and not the command mocha test?
index.js
'use strict';
var _ = require("underscore");
var async = require('async');
var argv = require("minimist")(process.argv.slice(2));
var getprotocol = require("./getProtocol");
var _getprotocol = getprotocol.getProtocol;
var S3rs = require("./S3resizer");
var s3resizer = S3rs.rs;
var objCr = require("./objectCreator");
var createObj = objCr.creator;
var fileRs = require("./fileResizer");
var fileResizer = fileRs.rs;
var configs = require("./configs.json");
var mkDir = require("./makeDir");
var makeDir = mkDir.handler;
exports.imageRs = function (event, context) {
var _path = argv.x || event.path; //argv.x used to be process.argv[2]
console.log("Path, %s", _path);
var _dir = argv.y; // used to be process.argv[3]
console.log(_dir);
var parts = _getprotocol(_path);
var imgName = parts.pathname.split("/").pop();
console.log("imgName: %s", imgName);
var s3Bucket = parts.hostname;
var s3Key = imgName;
var _protocol = parts.protocol;
console.log(_protocol);
// RegExp to check for image type
var imageTypeRegExp = /(?:(jpg)|(png)|(jpeg))$/;
var sizesConfigs = configs.sizes;
var obj = createObj(_path);
// Check if file has a supported image extension
var imgExt = imageTypeRegExp.exec(s3Key);
if (imgExt === null) {
console.error('unable to infer the image type for key %s', s3Key);
context.done(new Error('unable to infer the image type for key %s' + s3Key));
return;
}
var imageType = imgExt[1] || imgExt[2];
// Do more stuff here
};
if (!process.env.LAMBDA_TASK_ROOT) {
exports.imageRs();
}
test.js
describe("imgeRs", function () {
var getprotocol = require("../getProtocol");
var S3rs = require("../S3resizer");
var objCr = require("../objectCreator");
var mkDir = require("../makeDir");
var fileResizer = require("../fileResizer");
describe("Calling S3", function () {
describe("Success call", function () {
var testedModule, eventObj, contextDoneSpy, S3resizerStub, objCreatorStub, getProtocolStub, fakeResults, mkDirStub, fileResizerStub;
before(function (done) {
contextDoneSpy = sinon.spy();
S3resizerStub = sinon.stub(S3rs, "rs");
objCreatorStub = sinon.stub(objCr, 'creator');
getProtocolStub = sinon.stub(getprotocol, "getProtocol");
mkDirStub = sinon.stub(mkDir, "handler");
fileResizerStub = sinon.stub(fileResizer, "rs");
eventObj = {"path": "s3://theBucket/image.jpeg"};
fakeResults = ["resized"];
testedModule = proxyquire("../index", {
'./getProtocol': {
'getProtocol': getProtocolStub
},
'./S3resizer': {
'rs': S3resizerStub
},
'./objectCreator': {
'creator': objCreatorStub
},
'./makeDir': {
'handler': mkDirStub
},
'./fileResizer': {
'rs': fileResizerStub
}
});
S3resizerStub.callsArgWith(5, null, fakeResults);
testedModule.imageRs(eventObj, {done: function (error) {
contextDoneSpy.apply(null, arguments);
done();
}});
});
after(function () {
S3rs.rs.restore();
objCr.creator.restore();
getprotocol.getProtocol.restore();
mkDir.handler.restore();
fileResizer.rs.restore();
});
it("calls context.done with no error", function () {
expect(contextDoneSpy).has.been.called;
});
});
});
});

Q.js variables passing in parallel flows

While implementing promises got this code:
var MongoClient = require('mongodb').MongoClient
MongoClient.connect(db_uri, function(err, db) {
if(err) throw err;
var ccoll = db.collection('cdata');
app.locals.dbstore = db;
}
var json= {}
//Auth is a wrapped mongo collection
var Auth = app.locals.Auth;
var coll = app.locals.dbstore.collection('data');
var ucoll = app.locals.dbstore.collection('udata');
var ccoll = app.locals.dbstore.collection('cdata');
var Q = require('q');
//testing with certain _id in database
var _id = require('mongodb').ObjectID('530ede30ae797394160a6856');
//Auth.getUserById = collection.findOne()
var getUser = Q.nbind(Auth.getUserById, Auth);
//getUserInfo gives a detailed information about each user
var getUserInfo = Q.nbind(ucoll.findOne, ucoll);
var getUserData = Q.nbind(ccoll.findOne, ccoll);
//"upr" is a group of users
//getUsers gives me a list of users, belonging to this group
var getUsers = Q.nbind(ucoll.find, ucoll);
//Auth.getUserById = collection.find()
var listUsers = Q.nbind(Auth.listUsers, Auth);
var uupr = {}
var cupr = {}
getUserInfo({_id:_id})
.then(function(entry){
console.log('entry:', entry);
uupr = entry;
var queue = [getUsers({upr:entry.name}), getUserData({_id:entry._id})]
return Q.all(queue);
}
)
.then(function(array2){
console.log('array2:', array2);
cupr = array2[1]
var cursor = array2[0]
var cfill = Q.nbind(cursor.toArray, cursor);
return cfill();
}
)
.then(function(data){
json = {data:data, uupr:uupr, cupr:cupr}
console.log('json:', json)
res.render('test', {json : JSON.stringify(json)})
}
)
Its work can be described by a diagram:
getUserInfo()==>(entry)--+-->getUsers()=====>array2[0]--+-->populate user list===>data--->render
| |
+-->getUserData()==>array2[1]--+
I've used external variables uupr and cupr to store data from first .then calls.
So I have two problems:
1) Avoid using external variables.
2) rearrange code to get alternative flow diagram.
getUserInfo()==>(entry)--+-->getUsers()==>usersList-->populate user list==>usersData-+->render
| |
+-->getUserData()====>uprData-------------------------------+
Any advice is appreciated
Try something along the lines of this pseudo-code:
getUserInfo().then(function(userInfo) {
return Q.all([
userInfo,
getUsers(... userInfo ...).then(convert to array),
getUserData(... userInfo ...)
])
}).spread(function(userInfo, usersArray, userData) {
res.render(...)
}, function(err) {
handle the error
}).done()
You can simply nest them:
getUserInfo({_id:_id})
.then(function(entry){
console.log('entry:', entry);
return Q.all([
getUsers({upr:entry.name}),
getUserData({_id:entry._id})
]);
.spread(function(cursor, cupr) {
console.log('array2:', [cursor, cupr]);
return Q.ninvoke(cursor, "toArray")
.then(function(data){
return {data:data, uupr:entry, cupr:cupr};
});
});
}).then(function(json) {
console.log('json:', json)
res.render('test', {json: JSON.stringify(json)})
});
Now, to let the toArray not wait for the getUserData result, just do those in parallel:
getUserInfo({_id:_id})
.then(function(entry){
console.log('entry:', entry);
return Q.all([
getUsers({upr:entry.name}).invoke("toArray"),
getUserData({_id:entry._id})
]);
.spread(function(data, cupr) {
return {data:data, uupr:entry, cupr:cupr};
});
}).then(function(json) {
console.log('json:', json)
res.render('test', {json: JSON.stringify(json)})
});
(Using invoke instead an explicit then)

Trying to use gridfs but something is not outputting correctly

Hey so I am trying to use gridfs to store profile pictures... I am not sure what I am doing wrong, I am kind of new to this as well.
This is what I got so far, but it seems to be erroring this:
TypeError: Cannot read property 'primary' of undefined
at Stream.GridStore.open (..\node_modules\mongodb\lib\mongodb\gridfs\gridstore.js:146:69)
This is my code:
var mongoose = require('mongoose'),
Schema = mongoose.Schema,
ObjectId = mongoose.Schema.Types.ObjectId;
var GridStore = require('mongodb').GridStore;
var Step = require('step');
exports.newProfilePicturePost = function(req, res) {
var db = mongoose.createConnection('mongodb://localhost/test5');
var fileId = new ObjectId();
var gridStore = new GridStore(db, fileId, "w", {
"metadata": {
category: 'image'
}, content_type: 'image'});
gridStore.chunkSize = 1024 * 256;
gridStore.open(function(err, gridStore) {
Step(
function writeData() {
var group = this.group();
for(var i = 0; i < 1000000; i += 5000) {
gridStore.write(new Buffer(5000), group());
}
},
function doneWithWrite() {
gridStore.close(function(err, result) {
console.log("File has been written to GridFS");
});
}
)
});
};
Any help or fixes I should make to my code is welcomed, also I am not sure how to specify the collection I want to store the picture in and I want to also add the userId to the picture being saved in the collection for fetching it later.

Resources