I'm currently working on a Phonegap app, and I would like users to be able to upload any file to my NodeJS server.
I've looking all around the web but I just can't get anything to work...
Here is the code I'm using for the Phonegap controller:
$scope.open = function()
{
navigator.camera.getPicture(upload,
function(message)
{
alert('get picture failed');
},
{
quality: 50,
destinationType: navigator.camera.PictureSourceType.FILE_URI,
sourceType: navigator.camera.PictureSourceType.PHOTOLIBRARY,
mediaType: navigator.camera.MediaType.ALLMEDIA
});
}
var win = function (r) {
$scope.log = "Code = " + r.responseCode;
$scope.log2 = "Response = " + r.response;
$scope.log3 = "Sent = " + r.bytesSent;
$scope.$digest();
}
var fail = function (error) {
$scope.log = "An error has occurred: Code = " + error.code;
$scope.log2 = "upload error source " + error.source;
$scope.log3 = "upload error target " + error.target;
$scope.$digest();
}
function upload(fileURI)
{
$scope.log = fileURI;
$scope.$digest();
var options = new FileUploadOptions();
options.fileKey = "file";
options.fileName = fileURI.substr(fileURI.lastIndexOf('/') + 1);
options.mimeType = "text/plain";
options.chunkedMode = false;
var params = {};
params.value1 = "test";
params.value2 = "param";
options.params = params;
var ft = new FileTransfer();
ft.upload(fileURI, "http://192.168.192.111:2999/upload", win, fail, options);
}.
Here is the current code for the NodeJS server, have tried a lot of different things, all without success:
var express = require('express');
var http = require('http').Server(express);
var io = require('socket.io')(http);
var fs = require('fs');
var multer = require('multer');
var app = new express();
app.post('/upload', multer({dest: './uploads/'}).single('upl'), function(req, res)
{
console.log(req.body);
console.log(req.file);
})
http.listen(2999, function(){
console.log('listening on *:2999');
});
In the app I used to get errors that FileUploadOptions etc weren't defined, but I fixed that by adding them to the cordova project.
Furthermore, I use ionic 1, if that helps anyone out.
I do keep constantly getting the error code 1 (upload error source), even though I selected a real file and I saw that the link was correct (something like /storage/0/emulated/Downloads on my Android device).
Also, sometimes it gives me error 3 as well (upload target source), some sort of server not found issue I think.
Is there something obvious I'm doing wrong and how would I be able to fix it? Is there a handier way, since I eventually want to link this to a MySQL database.
Thanks in advance!
Well found my answer (a while ago, this is for people stumbling across this post).
You can first try whether your JS works by changing the server to https://posttestserver.com/post.php. If you see an upload appearing there, there's a problem with the server.
The problem with me was that I didn't let Apache through the firewall at all, so uploads from anything besides my PC would fail...
var express=require('express');
var bodyParser=require('body-parser');
var formidable = require('formidable');
var util = require('util');
var app=express();
app.use(bodyParser.urlencoded({ extended: false }));
app.use(bodyParser.json());
var path=require('path');
var mysql =require('mysql');
var fs=require('fs');
app.use('/public',express.static(path.join(__dirname, 'public')));
var connection = mysql.createConnection({
host: 'localhost',
user: 'root',
password : '',
port : 3306, //port mysql
database:'xxxxx'
});
app.post('/data', function(req, res) {
// create an incoming form object
var form = new formidable.IncomingForm(),
files = [],
fields = [];
// specify that we want to allow the user to upload multiple files in a single request
form.multiples = true;
// store all uploads in the /uploads directory
form.uploadDir = path.join(__dirname, '/public/images/uploads');
// every time a file has been uploaded successfully,
// rename it to it's orignal name
form.on('file', function(field, file) {
if (path.extname(file.name)=='') {
extension='.jpg';
}
else{
extension=path.extname(file.name);
}
var oldpath = file.path;
form.uploadDir = path.basename(file.name,extension).concat((Math.random()* 100),extension);
var newpath = './public/images/uploads/'+ path.basename(file.name,extension).concat((Math.random()* 100),extension);
//fs.rename(file.path, path.join(form.uploadDir, file.name));
fs.rename(oldpath, newpath);
});
form.on('field', function(field, value) {
fields[field] = value;
});
// log any errors that occur
form.on('error', function(err) {
console.log('An error has occured: \n' + err);
});
// once all the files have been uploaded, send a response to the client
//Call back at the end of the form.
form.on('end', function () {
res.writeHead(200, {
'content-type': 'text/plain'
});
res.write('received the data:\n\n');
// console.log(fields.name+'-'+fields.nickname);
var values={
name:fields.name,
nickname:fields.nickname,
email:fields.email,
password:fields.password,
dob:fields.dob,
gender:fields.gender,
phoneno:fields.phone
};
connection.query('INSERT INTO users SET ?', values, function(err,req,res){
if(err){
console.log('Connection result error '+err);
}
else{
console.log('Success');
}
});
res.end();
});
// parse the incoming request containing the form data
form.parse(req);
});
//app.use(app.router);
app.listen(5000);
Related
I am using Cloude 9 environment for developing my nodejs app. In that I have written code to connect to mongodb database. I am successfully connecting to database and adding record to collection.
Now I want to send the collection info in return. But using res.send(collectionInfo); is not working.
Let me know how should I achieve this
Below is the code of my server.js file
var Db = require('mongodb').Db;
var http = require('http');
var path = require('path');
var async = require('async');
var socketio = require('socket.io');
var express = require('express');
var ejs = require('ejs');
var app = express();
var helpers = require('express-helpers')
var MongoClient = require('mongodb').MongoClient;
var Server = require('mongodb').Server;
var db;
helpers(app);
var bodyParser = require('body-parser');
app.use(bodyParser.json()); // for parsing application/json
app.use(bodyParser.urlencoded({extended: true})); // for parsing application/x-www-form-urlencoded
var server = http.Server(app);
server.listen(process.env.PORT || 3000, process.env.IP || "0.0.0.0", function () {
var addr = server.address();
console.log("Chat server listening at", addr.address + ":" + addr.port);
});
app.use(express.static(__dirname + '/public'));
app.set('views', __dirname + '/public/views');
app.engine('html', require('ejs').renderFile);
app.set('view engine', 'html');
//app.use(express.static(__dirname + '/client'));
app.use(express.static(path.join(__dirname, '/client')));
// MongoDB Connection
app.use(function(req, res, next) {
next();
})
app.get('/monogdb', function (req, res) {
res.render('monogdb.ejs');
});
app.post('/ajax-mongo-connect', function (req, res) {
var mongoClient = new MongoClient(new Server('localhost', 27017));
mongoClient.open(function(err, mongoClient) {
if(err){
console.log(err);
}else{
var db = mongoClient.db("mydb");
db.createCollection("students", { name : req.body.nm, description : req.body.desc, location : req.body.loc } );
console.log('database connected',db);
var collectionInfo = db.collection("students");
mongoClient.close();
//res.setHeader('Content-Type', 'application/json');
res.send(collectionInfo);
}
})
})
As per #Roman Sachenko answer, I have tried to use
res.send(collectionInfo.toJSON()); but it is giving below error
/home/ubuntu/workspace/node_modules/mongodb/lib/mongodb/db.js:299
throw err;
^
TypeError: Object #<Collection> has no method 'toJSON'
at /home/ubuntu/workspace/server.js:66:41
at MongoClient.open
(/home/ubuntu/workspace/node_modules/mongodb/lib/mongodb/mongo_client.js:103:5)
at Db.open (/home/ubuntu/workspace/node_modules/mongodb/lib/mongodb/db.js:296:11)
at process._tickCallback (node.js:442:13)
and using res.send({data: collectionInfo}); gives error
home/ubuntu/workspace/node_modules/mongodb/lib/mongodb/db.js:299
throw err;
^
TypeError: Converting circular structure to JSON
at Object.stringify (native)
at ServerResponse.res.json (/home/ubuntu/workspace/node_modules/express/lib/response.js:185:19)
at ServerResponse.res.send (/home/ubuntu/workspace/node_modules/express/lib/response.js:117:21)
at /home/ubuntu/workspace/server.js:67:21
at MongoClient.open (/home/ubuntu/workspace/node_modules/mongodb/lib/mongodb/mongo_client.js:103:5)
at Db.open (/home/ubuntu/workspace/node_modules/mongodb/lib/mongodb/db.js:296:11)
at process._tickCallback (node.js:442:13)
Try to return this: res.status(200).json({'myCollection' : collectionInfo});.
You can find more details about express response here
Update:
After you explain the details, take a look at the code below:
app.post('/ajax-mongo-connect', function (req, res) {
var mongoClient = new MongoClient(new Server('localhost', 27017));
mongoClient.open(function(err, mongoClient) {
if(err){
console.log(err);
res.status(500).json({message : 'OMG, an error occurred'});
}else{
var db = mongoClient.db("mydb");
db.createCollection("students", { name : req.body.nm, description : req.body.desc, location : req.body.loc } );
console.log('database connected',db);
var collectionInfo = db.collection("students");
// Here we will find all students
collectionInfo.find({}).toArray(function(err, students) {
// so now, we can return all students to the screen.
res.status(200).json({'myCollection' : students});
}
}
})
})
Cheers!
Mongoose ODM
First of all I would like to recommend you using Mongoose ODM:
https://github.com/Automattic/mongoose
So you will make you work with database much easier.
Basically it returns (Mongoose) normal object as results, but in case of issues you may try to use toObject() or toJSON() or as it mentioned create own object like {data: mongoCollection}
Examples:
res.send(collectionInfo.toObject());
res.send(collectionInfo.toJSON());
res.send({data: collectionInfo});
Please refer to the link in case of questions:
http://mongoosejs.com/docs/guide.html#toJSON
Native Driver
As for native driver, it also should return normally-constructed object, but according to issues I faced with in the past, JSON.stringify always helps if you set headers manually.
You may also check the contents of your entity. So you can just output it by console.log(collectionInfo);
Then just make sure that there is correct object inside.
And according to results you can take actions like:
res.send(JSON.stringify(collectionInfo)) //set headers manually
res.json(JSON.stringify(collectionInfo)) //you don't need to set headers
At least you will know what exactly is inside of collectionInfo. I think it will be enough to investigate the issue.
You can view circular JSON objects by doing this in node.js:
const util = require('util') // Native node module
util.inspect(circularObj)
You can call it from anywhere in the code, so it's very versatile.
Hi Am facing "failed to start accepting connection" error while pushing or deploying my app to bluemix. Can any help me in that.... my code snippet as given below:
var express = require('express');
app = express();
var ibmbluemix = require('ibmbluemix')
var ibmdb = require('ibm_db');
var http = require('http');
var url = require('url');
var logger = ibmbluemix.getLogger();
var PORT = (process.env.VCAP_APP_PORT || 8000);
var HOST = (process.env.VCAP_APP_HOST || 'localhost');
var queryData = null;
var serviceName = 'SQLDB';
if (process.env.VCAP_SERVICES) {
var env = JSON.parse(process.env.VCAP_SERVICES);
db2 = env['sqldb'][0].credentials;
}
else{
console.error("INFORMATION FOR DB CONNECTION NOT FOUND");
}
var dbConnection = "DRIVER={DB2};DATABASE=" + db2.db + ";UID=" + db2.username + ";PWD=" + db2.password + ";HOSTNAME=" + db2.hostname + ";port=" + db2.port;
console.log("Connection String: " + dbConnection);
http.createServer(function(request, response) {
console.log('Creating the http server');
ibmdb.open(dbConnection, function(err, conn) {
if (err) {
response.send("error occurred " + err.message);
}
else {
console.log('before select');
conn.query("SELECT FULL_NAME, PASSWORD, SHORT_ID FROM USER02130.USER_DETAILS", function(err, rows, moreResultSets) {
console.log('Connection result error '+err);
console.log('no of records is '+rows.length);
response.writeHead(200, { 'Content-Type': 'application/json'});
response.write(JSON.stringify(rows));
response.end();
});
}
}).listen(PORT, HOST);
Can anyone help me in this, Thanks in advance
There are a few syntactical errors in your snippet (missing closing brackets etc). Try using this instead:
var express = require('express');
app = express();
var ibmbluemix = require('ibmbluemix')
var ibmdb = require('ibm_db');
var http = require('http');
var url = require('url');
var logger = ibmbluemix.getLogger();
var PORT = (process.env.VCAP_APP_PORT || 8000);
var HOST = (process.env.VCAP_APP_HOST || 'localhost');
var queryData = null;
var serviceName = 'SQLDB';
if (process.env.VCAP_SERVICES) {
var env = JSON.parse(process.env.VCAP_SERVICES);
var db2 = env['sqldb'][0].credentials; // missed declaration
}
else{
console.error("INFORMATION FOR DB CONNECTION NOT FOUND");
}
var dbConnection = "DRIVER={DB2};DATABASE=" + db2.db + ";UID=" + db2.username + ";PWD=" + db2.password + ";HOSTNAME=" + db2.hostname + ";port=" + db2.port;
console.log("Connection String: " + dbConnection);
http.createServer(function(request, response) {
console.log('server request'); // does not create a server on every request
ibmdb.open(dbConnection, function(err, conn) {
if (err) {
response.send("error occurred " + err.message);
}
else {
console.log('before select');
conn.query("SELECT FULL_NAME, PASSWORD, SHORT_ID FROM USER02130.USER_DETAILS", function(err, rows, moreResultSets) {
console.log('Connection result error '+err);
console.log('no of records is '+rows.length);
response.writeHead(200, { 'Content-Type': 'application/json'});
response.write(JSON.stringify(rows));
response.end();
});
}
}) // missed closing brackets
}).listen(PORT, HOST);
console.log("Server running at "+HOST+" on port "+ PORT);
Node.js is very easy to set up locally, get it here. Running it locally can help you identify many problems, such as syntactical error.
Hope it helps!
cf logs <app name> --recent
This command will give you the logs which will show you where your syntax errors were.
It's great that you figured it out, but for future reference, the “failed to start accepting connection” error usually means the code threw an exception during initialization before calling http.createServer(...).listen(port, host). Try adding the code below prior to the call to listen(...)
process.on('uncaughtException', function (err) {
console.log(err);
});
Your console logs will then include a helpful stack trace if the startup code fails for an unforeseen reason instead of receiving the default "app crashed" message.
Still stuck? Pat Mueller offers other helpful suggestions in Node.js debugging starts with better logging! and David Clements' Node.js tips #1: develop debugging techniques offers more advanced debugging tips, e.g., function de-anonymizing.
I need help in trying to solve this scenario
I have a file web.js. Over there I have
var express = require("express");
var app = express();
var web2 = require("./web2");
/* Code the start the server on the required port*/
app.get('/param1', function(req, res){
console.log("INSIDE GET METHOD OF WEB.JS");
});
module.exports.app = app
I have another file web2.js. over there I have
var web = require("./web");
app = web.app;
app.get('/param2', function(req, res){
console.log("INSIDE GET METHOD OF WEB2.JS");
});
While starting I get an error
TypeError: Cannot call method 'post' of undefined
If I remove the line 3 from web.js -- I am able to start the server, but a request for http:///param2 gives a 404
Updated scenario:
I am using pg database and I try to create a client that keeps an instance of the client(in web.js). I then pass this to other file(web2.js). In web.js I always get this client as null
in web.js I have the following code
var pg = require("pg");
var pgclient;
app.get('*', function(req,res,next){
pg.connect(process.env.DATABASE_URL, function(err, client, done) {
if(client != null){
pgclient = client;
console.log("Client connection with Postgres DB is established");
next();
}
}
}
require("./web2.js")(app, pgclient);
in web2.js, I have the following code
module.exports = function(app, pgclient){
app.get('/param1', function(req,res){
if(pgclient != null){
}
else{
res.send(500, "pgclient is NULL");
}
});
}
The code never reaches the if block(if(pgclient != null)) in web2.js
The problem is the cyclic dependency between web.js and web2.js. When web2.js requires web.js, web.js's module.exports hasn't been set yet. I would rather do something like this:
web.js
var express = require("express");
var app = express();
app.get("/param1", function (req, res) {
// ...
});
require("./web2")(app);
app.listen(/* port number */);
web2.js
module.exports = function (app) {
app.get("/param2", function (req, res) {
// ...
});
};
I have a working code - when it comes to uploading the file ::
var express=require('express');
var mysql=require('mysql');
var fs=require('fs');
var http=require('http');
var crypto=require('crypto');
var app=express();
var connection=mysql.createConnection({
host:'localhost',
user:'****',
password:'****',
database:'posting_only_image_DB'
});
connection.connect();
app.set('port',process.env.PORT||1234);
app.use(express.static(__dirname+'/public/images'));
app.use(express.bodyParser());
app.post('/Details/',function(req,res,next){
var file_name=req.files.key.originalFilename;
console.log(file_name);
crypto.randomBytes(8, function(ex, buf) {
var array = req.files.key.originalFilename.split('.');
var type = array[array.length - 1];
var name = buf.toString('hex') + '.' + type;
fs.rename(req.files.key.path, './public/images/' + name, function(e) {
next(e, name);
});
});
});
http.createServer(app).listen(app.get('port'),function(){
console.log('Express server listening on port'+app.get('port'));
});
I make a request as below while uploading the file::
however my query works and i can see the file with unique id in server disk in location /public/images .... with the file name:: 8ce456dc55575888.jpg
Now say if i want to test it and i want to view the uploaded file :: I five a Url request to below for the browser
http://-----URL----/Details/8ce456dc55575888.jpg
I get the error on browser as ::
Cannot GET /Details/8ce456dc55575888.jpg
How to resolve this ?
You don't have a GET route for /Details/8ce456dc55575888.jpg.
If you want the static middleware to handle those requests, you need to configure it properly:
app.use('/Details', express.static(__dirname+'/public/images'));
This means that requests for:
/Details/8ce456dc55575888.jpg
Will be mapped to:
{{__dirname}}/public/images/8ce456dc55575888.jpg
You can use that in addition to the other express.static that you're using.
I'm using Express.js and MongoLab and I followed the Heroku setup to get MongoDB working in production throwing this code in my app.js.
//Mongo on Heroku Setup
var mongo = require('mongodb');
var mongoUri = process.env.MONGOLAB_URI ||
process.env.MONGOHQ_URL ||
'mongodb://localhost/mydb';
mongo.Db.connect(mongoUri, function (err, db) {
db.collection('mydocs', function(er, collection) {
collection.insert({'mykey': 'myvalue'}, {safe: true}, function(er,rs) {
});
});
});
and I have the following routes and field for my email form (also in app.js):
//Routes
app.get('/', function(req, res) {
res.render('index', {
title: 'DumbyApp'
});
});
//save new email
app.post('/', function(req, res){
emailProvider.save({
address: req.param('address')
}, function( error, docs) {
res.redirect('/')
});
});
This renders the new form on the index page and lets me save it locally but not in production because I don't know how to setup my email collection. Can anyone walk me through this? brand new to using MongoDB and Node.js, so could use some help.
EDIT:
In The MongoLab Database Interface, I made a collection called emails. Is this the right course of action?
EDIT 2:
Here's defining EmailProvider in app.js along with the file itself.
app.js
var express = require('express')
, routes = require('./routes')
, user = require('./routes/user')
, http = require('http')
, path = require('path')
, EmailProvider = require('./emailprovider').EmailProvider;
var emailProvider= new EmailProvider('localhost', 27017);
emailprovider.js
var Db = require('mongodb').Db;
var Connection = require('mongodb').Connection;
var Server = require('mongodb').Server;
var BSON = require('mongodb').BSON;
var ObjectID = require('mongodb').ObjectID;
EmailProvider = function(host, port) {
this.db= new Db('localdb', new Server(host, port, {safe: false}, {auto_reconnect: true}, {}));
this.db.open(function(){});
};
EmailProvider.prototype.getCollection= function(callback) {
this.db.collection('emails', function(error, email_collection) {
if( error ) callback(error);
else callback(null, email_collection);
});
};
//save new email
EmailProvider.prototype.save = function(emails, callback) {
this.getCollection(function(error, email_collection) {
if( error ) callback(error)
else {
if( typeof(emails.address)=="undefined")
emails = [emails];
for( var i =0;i< emails.address;i++ ) {
email = emails[i];
email.created_at = new Date();
}
email_collection.insert(emails, function() {
callback(null, emails);
});
}
});
};
exports.EmailProvider = EmailProvider;
While the connection code in the first code box appears to be correct, the emailProvider object isn't using it. Instead, in app.js, the EmailProvider is being connected to localhost:27017 and the database name is hardcoded in emailprovider.js as 'localdb'.
What you want to do instead is use the connection information provided in the MONGOLAB_URI environment variable in your EmailProvider, which contains the host, port, and database name already.
There are a number of ways to go about doing this, but one way would be to move your connection code from that first code box into the EmailProvider constructor, and then change the constructor so that it takes a URI instead of a host and port. That way, you can pass the MONGOLAB_URI variable to the constructor in app.js.