node.js and express file uploader - javascript

So I am following this tutorial: http://thejackalofjavascript.com/uploading-files-made-fun/
I have followed the steps all the way up to where they create the routes and haven't actually created any views. It says
Thats it we are all done with our server. Restart your server and
navigate to http://localhost:3000/upload. You should see a JSON
response with the empty array of files.
However when I try to run app.js it sits for a few seconds and then just goes back to the command prompt. No errors are given and I am clueless as to how to fix this.
Here is my code in routes/uploadManager.js
var options = {
tmpDir: __dirname + '/../public/uploaded/tmp',
uploadDir: __dirname + '/../public/uploaded/files',
uploadUrl: '/uploaded/files/',
maxPostSize: 11000000000, // 11 GB
minFileSize: 1,
maxFileSize: 10000000000, // 10 GB
acceptFileTypes: /.+/i,
// Files not matched by this regular expression force a download dialog,
// to prevent executing any scripts in the context of the service domain:
inlineFileTypes: /\.(gif|jpe?g|png)/i,
imageTypes: /\.(gif|jpe?g|png)/i,
imageVersions: {
width: 80,
height: 80
},
accessControl: {
allowOrigin: '*',
allowMethods: 'OPTIONS, HEAD, GET, POST, PUT, DELETE',
allowHeaders: 'Content-Type, Content-Range, Content-Disposition'
},
storage : {
type : 'local'
}
};
var uploader = require('blueimp-file-upload-expressjs')(options);
module.exports = function (router) {
router.get('/upload', function (req, res) {
uploader.get(req, res, function (obj) {
res.send(JSON.stringify(obj));
});
});
router.post('/upload', function (req, res) {
uploader.post(req, res, function (obj) {
res.send(JSON.stringify(obj));
});
});
router.delete('/uploaded/files/:name', function (req, res) {
uploader.delete(req, res, function (obj) {
res.send(JSON.stringify(obj));
});
});
return router;
}

I apologize. I was trying to run node app.js when I was supposed to be running node bin/www since this is an express.js app.

Related

How to modularize an express app - with a function, a class and req.pipe?

Here below there are two servers and two gqlServers. All combinations of them work.
The challenge is to extend express with some additional predefined code patterns shared across several apps, exposed through additional methods.
Which combination of a server and gqlServer is considered best practice and best for performance?
server:
server_A is a function that returns a class
server_B is a function that returns a function
gqlServer:
gqlServer_01 uses req.pipe
gqlServer_02 has the original express() passed into it
function gqlServer_01(options) {
let gqlApp = express();
gqlApp.use(options.route, function(req, res, next) {
res.send('gqlServer 01');
// next();
});
gqlApp.listen(8001, err => {
if (err) throw err;
console.log(`>> GQL Server running on 8001`);
});
}
function gqlServer_02(app, options) {
app.use(options.route, function(req, res, next) {
res.send('gqlServer 02');
// next();
});
}
// THIS SERVER ?
function server_A(config = {}) {
config = deepmerge(def_opt, config);
let app = express();
app.get('/', function(req, res, next) {
res.send('root');
// next();
});
class Server {
constructor(opt) {
this.opt = opt;
}
gql(props = {}) {
// THIS GQL SERVER ?
gqlServer_01({ route: '/gql-01' });
app.use('/gql-01', function(req, res) {
req.pipe(request(`http://localhost:8001/gql-01`)).pipe(res);
});
// OR THIS GQL SERVER ?
gqlServer_02(app, { route: '/gql-02' });
}
}
app.listen(8000, err => {
if (err) throw err;
console.log(`>> Server running on 8000`);
});
return new Server(app, config);
}
// OR THIS SERVER ?
function server_B(config = {}) {
config = deepmerge(def_opt, config);
let app = express();
app.get('/', function(req, res, next) {
res.send('root');
// next();
});
app.gql = function(props = {}) {
// THIS GQL SERVER ?
gqlServer_01({ route: '/gql-01' });
app.use('/gql-01', function(req, res) {
req.pipe(request(`http://localhost:8001/gql-01`)).pipe(res);
});
// OR THIS GQL SERVER ?
gqlServer_02(app, { route: '/gql-02' });
};
app.listen(8000, err => {
if (err) throw err;
console.log(`>> Server running on 8000`);
});
return app;
}
The goal is to have the best solution in order to create an npm package out of this and reuse the methods over several projects easily. The project was highly simplified for the sake of clarity.
I don't think you will have performance issues in any of these examples, so the question remains which of them is more modular.
If you are willing to make an npm package out of these, you shouldn't be calling express() inside your server code. Instead you should be passing the app as a parameter. This will allow you to reuse existing express apps initialized elsewhere. For this reason I would go for gqlServer_02
You also want to create a new server each time you call the module function, so I'd go with server_A for this reason. However it needs to receive the express app as parameter, in order to reuse existing express objects. I would also put the app.listen call inside a function in the Server class.

Cannot GET /the route Error

I'm following this tutorial (source code) and added the highlighted code.
// app.js
app.get("/notebooks", function(req, res) {
var client = new Evernote.Client({ token: req.session.oauthAccessToken }),
noteStore = client.getNoteStore();
noteStore.listNotebooks(function(err, noteBooks) {
res.send(err || noteBooks);
});
});
app.get('/importNotes', function (req, res) {
res.send('importNotes');
});
app.get("/notes/:guid", function(req, res) {
var client = new Evernote.Client({ token: req.session.oauthAccessToken }),
noteStore = client.getNoteStore();
noteStore.getNote(req.params.guid, true, true, true, true, function(err, note) {
if (!err) {
note.content = ENML.HTMLOfENML(note.content, note.resources);
}
res.send(err || note);
});
});
another attempt:
app.get('/importNotes', function (req, res) {
res.render('importNotes', {});
});
I created importNotes.html near to index.html.
After starting the server with node app.js
I'm getting an error stating Cannot GET /importNotes
when I access localhost:3000/importNotes
I plan to use this page to add additional features after I deal with this issue (import the notes from the special txt file).
What I'm doing wrong and how I can correct it?
How to define correctly the needed routes ?
This is Steve - thanks for trying out the code !
If you use this code :
app.get('/importNotes', function (req, res) {
res.send('importNotes');
});
Then I would expect the server will send back to the browser the string "importNotes". Perhaps if you have a file called "importNotes" there is some confusion.
If you want to create a file called importNotes.html - then just put it into the "public" folder. It will then be accessible via localhost:3000/importNotes.html
The line :
app.use(express.static(__dirname + "/public"));
Tells Express to serve the contents of the "public" folder at the root level of your application, so any files you put in that folder should be GETable. e.g.
/public
index.html
steve.html
localhost:3000/steve.html

How to send response to client when files is too large with Multer

I'm using NodeJs Multer to upload files. I need to send response back to a client when file user tries to upload is too large. The problem is that onFileSizeLimit only has file as argument and I dont know how to send response to client. What I need to do is basically soomething like below:
app.use('/users/gyms/upload-logo', multer({
// other settings here then:
onFileSizeLimit: function (file) {
// but res (response) object is not existing here
res.json({
message: "Upload failed",
status: MARankings.Enums.Status.FILE_TOO_LARGE
// status: -6
});
}
});
res object dosent exists in there however and I'm wondering what is the best way to send some sort of response to client.
try this:
app.use('/users/gyms/upload-logo', multer({
// other settings here then:
onFileSizeLimit: function (file) {
// but res (response) object is not existing here
file.error = {
message: "Upload failed",
status: MARankings.Enums.Status.FILE_TOO_LARGE
// status: -6
};
}, onFileUploadComplete: function (file, req, res) {
if (file.error){
res.send(file.error);
}
}
});
In this case, it's good to remember that Multer itself is just a (middleware) function that Express calls to get its response.
You could perhaps try with this:
app.use('/users/gyms/upload-logo', function(req, res, next) {
var handler = multer({
// other settings here then:
onFileSizeLimit: function (file) {
// res does exist here now :)
res.json({
message: "Upload failed",
status: MARankings.Enums.Status.FILE_TOO_LARGE
// status: -6
});
}
});
handler(req, res, next);
});
This basically aliases multer to handler, passes req, res, next from the Express callback, and means you get access to the req, res, next variables from within Multer's configuration.
I haven't tested this but I think the theory is sound!
This is an issue which has not been resolved by the author of multer yet. This github issue has quite a lot of discussion about it:
There is one work around which I have used in my current project
File: make-middleware.js
change "function done(err)" at end of this function
Replace
Line 52: onFinished(req, function () { next(err) })
With:
Line 52: onFinished(req, function () { if(err.code == 'LIMIT_FILE_SIZE') { req.fileSizeError = 1; next() } else next(err) })
And in app file you can change the code to
app.post('/upload', upload.single('upload'), function (req, res, next) {
if(typeof req.fileSizeError != "undefined") {
res.send({"error":"File too large"});// to display filesize error
} else {
res.send({"file":req.file}); // when file uploaded successfully
}
});
The multer file object actually contains a property indicating whether the file exceeded the size limit. See https://www.npmjs.com/package/multer#multer-file-object
To accept only one file with a maximum size of 2 MB and the name "data" I did something like this:
app.use(multer({
dest: "./uploads/",
putSingleFilesInArray: true, // see https://www.npmjs.com/package/multer#putsinglefilesinarray
limits: {
files: 1,
fileSize: 2097152 // 2 MB
}
}));
app.post("/foo", function(request, response) {
if (!request.files.hasOwnProperty("data")) {
// 400 Bad Request
return response.status(400).end();
}
var file = request.files.data[0];
if (file.truncated) {
// 413 Request Entity Too Large
console.log("Request aborted.");
return response.status(413).end();
}
// do stuff with file
});

How to break this Node code into different files

I want to put code such as
app.use("/localAssets", express.static(__dirname + '/localAssets'));
app.use("/scripts", express.static(__dirname + '/scripts'));
in a different file, right now it is in the main server file but I do not like that. I also don't like that all the scoket event handling is also in the main server file.
ie
function onSocketConnection(client) {
//player connected
// Listen for client disconnected
client.on("disconnect", onClientDisconnect);
client.on('sendMessage', function (data) {
this.broadcast.emit('message', data);
this.emit('message', { text: data.text});
});
// Listen for new player message
client.on("new player", onNewPlayer);
// Listen for move player message
client.on("move player", onMovePlayer);
client.on("update health", onUpdateHealth);
client.on("attack hits", onHitByAttack);
client.on("meteor cast", onMeteorCast)
};
function onClientDisconnect() {
...
}
Please advise!
Here is the full file I want to sort out:
https://gist.github.com/hassanshaikley/337e5b7b7a8206a54418
Just put anything you want into different files inside of a function like this:
module.exports = function() {
// your code here
};
Then require and call that function, passing in whatever reference it may need, such as app:
// my-file.js
module.exports = function(app) {
// your code here
};
// index.js
require('./path/to/my-file')(app);
Here's a basic example of moving routes into another file:
// index.js
require('./path/to/some-routes')(app);
// some-routes.js
module.exports = function(app) {
app.get('/foo', function(req, res) {
res.send('Hi! This is foo.');
});
app.get('/bar', function(req, res) {
res.send('Hi! This is bar.');
});
app.get('/:me', function(req, res) {
res.send('Hi! This is '+req.params.me);
});
};

CORS issue on express/NodeJS, services not available from Internet Explorer

I have a REST based service written on Express/NodeJS . I have written code for
CORS (Cross Origin Resource Sharing) Implementation . And services can be consumed from browsers like chrome, firefox etc.. but not from Internet explorer, (I am using IE9, I checked witrh IE-10,CORS error message is still there in console)
CODE FROM routes.js File on node server side
var config = require('./config.js');
exports.setup = function (params) {
var controllers = params.controllers;
var app = params.app;
// CORS (Cross Origin Resource Sharing) Implementation
app.all('/*', function(req, res, next) {
res.header("Access-Control-Allow-Credentials", config.responseSettings.AccessControlAllowCredentials);
res.header("Access-Control-Allow-Origin", (req.headers.origin) ? req.headers.origin : config.responseSettings.AccessControlAllowOrigin);
res.header("Access-Control-Allow-Headers", (req.headers['access-control-request-headers']) ? req.headers['access-control-request-headers'] : "x-requested-with");
res.header("Access-Control-Allow-Methods", (req.headers['access-control-request-method']) ? req.headers['access-control-request-method'] : config.responseSettings.AccessControlAllowMethods);
next();
});
app.get('/', function(req, res) {
res.render('index', { title: 'Welcome })
});
function auth(req, res, next) {
if (req.session.UserId || (req.query.apikey && config.apikeys.indexOf(req.query.apikey) > -1)) {
next();
} else {
res.send(401);
}
}
app.get('/Session/:id?', controllers.SessionController.getSession);
app.post('/Session', controllers.SessionController.createSession);
app.del('/Session/:id', controllers.SessionController.deleteSession);
...
}
Following is the code of config.jf file
module.exports = {
"db": {
"mongodb": "mongodb://admin:XYX123#localhost/xyx",
"username": "abc",
"password": "abc123",
"database": "abcdb",
"server": "localhost"
},
"cookiesecret": "TWFuIGlzIGRpc3Rpbmd1aXNoZWQsIG5vdCBvbmx5IGJ5IGhpcyByZWFzb24sIGJ1dCBieSB0aGlz",
"responseSettings": {
"AccessControlAllowOrigin": "*",
"AccessControlAllowHeaders": "X-CSRF-Token, X-Requested-With, Accept, Accept-Version, Content-Length, Content-MD5, Content-Type, Date, X-Api-Version",
"AccessControlAllowMethods": "POST,GET,PUT,DELETE",
"AccessControlAllowCredentials": true
},
"apikeys": ['587c57365b54e8283fd6b1ac24acf29d', '4de04266bdd87410de698cfc33c55d68', '232c0252cee5e97148636ee2efd6ee94'], //only 1 is used now
};
And this is my server.js(app.js) file
// Configuration
app.configure(function () {
app.set('views', __dirname + '/views');
app.set('view engine', 'jade');
app.use(express.bodyParser());
app.use(express.methodOverride());
app.use(express.cookieParser());
app.use(express.session({ // to set a time here only for session expire
secret: config.cookiesecret,
store: new MongoStore({ db: config.db.database, host: config.db.server, username: config.db.username, password: config.db.password })
}));
app.use(app.router);
app.use(express.static(__dirname + '/public'));
});
app.configure('development', function () {
app.use(express.errorHandler({ dumpExceptions: true, showStack: true }));
});
app.configure('production', function () {
app.use(express.errorHandler());
});
// Routes
routes.setup({
'controllers': controllers,
'app': app
});
app.listen(process.env.port || 3000);
console.log("Express server listening on port %d in %s mode", app.address().port, app.settings.env);
The services cannot be obtained from IE. This is the first application I am doing in this stack,and my understanding is limited.please suggest a solution.
Client side is done in Backbonejs:This is the code from client-side
define([
'config',
'jquery',
'underscore',
'backbone'
], function (config, $, _, Backbone) {
var SessionModel = Backbone.Model.extend({
urlRoot: config.BaseUrl + '/Session',
initialize: function () {
var that = this;
$.ajaxPrefilter(function (options, originalOptions, jqXHR) {
options.xhrFields = {
withCredentials: true
};
})
},
login: function (creds, callback) {
// Do a POST to /session and send the serialized form creds
this.save(creds, {
success: callback
});
},
logout: function (callback) {
// Do a DELETE to /session and clear the clientside data
var that = this;
this.destroy({
success: function (model, resp) {
model.clear()
model.id = null;
// Set auth to false to trigger a change:auth event
// The server also returns a new csrf token so that
// the user can relogin without refreshing the page
that.set({ auth: false });
callback();
}
});
},
getAuth: function (callback) {
// getAuth is wrapped around our router
// before we start any routers let us see if the user is valid
this.fetch({
//success: callback
success: function (req, res) {
//alert("success");
callback();
},
error: function (err) {
//alert("error");
callback();
}
});
}
});
return new SessionModel;
});
"getAuth" is the function that runs first, it alerts- Success while running on chrome and firefox, but alerts error from IE
As commented by Bill, IE uses XDR. The solution you are looking for is here: https://github.com/jaubourg/ajaxHooks/blob/master/src/xdr.js
Basically I have that code on one of my initial JS files (after jQuery is loaded) and that will do the trick.

Categories