I really apologize if I'm leaving something out and am totally stupid, but I've checked and checked over again a number of times, and the file upload functionality is just not working over here. I made a super minimal app to demonstate. Just generated a new express app with the most up-to-date version (3.4.7) and added the least i could to make a file upload work.
Here's my app.js file
/**
* Module dependencies.
*/
var express = require('express');
var http = require('http');
var path = require('path');
var app = express();
// all environments
app.set('port', process.env.PORT || 3000);
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'jade');
app.use(express.favicon());
app.use(express.logger('dev'));
app.use(express.json());
app.use(express.urlencoded());
app.use(express.methodOverride());
app.use(app.router);
app.use(express.static(path.join(__dirname, 'public')));
// development only
if ('development' == app.get('env')) {
app.use(express.errorHandler());
}
app.get('/tasks', function(req, res) {
res.render('form');
});
app.post('/tasks', function(req, res) {
console.log(req.files);
res.send('ok');
});
http.createServer(app).listen(app.get('port'), function(){
console.log('Express server listening on port ' + app.get('port'));
});
exports = module.exports = app;
And here's my form.jade view file:
doctype html
html
head
title Task Upload
body
form(action='/tasks', method='post', enctype='multipart/form-data')
input(name='task', type='file')
input(type='submit')
Everytime I try to upload a file, req.files logs out undefined. Can anyone save me out from this problem?
Add the following in your app.js
app.configure(function(){
app.use(express.methodOverride());
app.use(express.bodyParser({keepExtensions:true,uploadDir:path.join(__dirname,'/files'}));
});
And then try to access as follows;
req.files.task
It is recommended not to use bodyParser, but to simply define the type of handling you want. In your case since its file uploading, you can enable it as follows
app.configure(function(){
app.use(express.methodOverride());
app.use(express.multipart());
});
You can read about why using bodyParser() is not a good idea in the following link.
http://andrewkelley.me/post/do-not-use-bodyparser-with-express-js.html
In Express 4, req.files is no longer available on the req object by default.
To access uploaded files on the req.files object, use multipart-handling middleware like busboy, multer, formidable, multiparty, connect-multiparty,.
Related
New to Node.js.
I'm using the VS2015 Express 3 template. How can I write my routing to:
Have a page at "/"
Have a a catch all route that responds with the home page "/"
Doesn't interfere with JS and CSS files
I.e., I tried the following, but then the JS and CSS files in the public directory respond with 404 don't render or execute. I thought that the static files code would handle it, but it does not. It works until I add the block with "*".
var express = require('express');
var routes = require('./routes');
var http = require('http');
var path = require('path');
var app = express();
// all environments
app.set('port', process.env.PORT || 3000);
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'jade');
app.use(express.favicon());
app.use(express.logger('dev'));
app.use(express.json());
app.use(express.urlencoded());
app.use(express.methodOverride());
app.use(app.router);
app.use(require('stylus').middleware(path.join(__dirname, 'public')));
app.use(express.static(path.join(__dirname, 'public')));
// development only
if ('development' == app.get('env')) {
app.use(express.errorHandler());
}
app.get('/', routes.index);
app.get('*', function (req, res) {
res.send('/', 404);
});
http.createServer(app).listen(app.get('port'), function () {
console.log('Express server listening on port ' + app.get('port'));
});
The solution, as suggested by jfriend00, is to add the following line below app.get('/', routes.index):
app.use(routes.index);
I'v got express app like this.
var express = require('express');
var http = require('http');
var path = require('path');
var app = express();
// all environments
app.set('port', process.env.PORT || 3000);
app.set('views', __dirname + '/views');
app.set('view engine', 'ejs');
app.use(express.favicon());
app.use(express.logger('dev'));
app.use(express.bodyParser());
app.use(express.methodOverride());
app.use(express.cookieParser());
app.use(express.static(path.join(__dirname, 'public')));
app.use(app.router);
app.get('*', function(res,req) {
req.render('index', {title: "Title"});
});
http.createServer(app).listen(app.get('port'), function () {
console.log('Express server listening on port ' + app.get('port'));
});
Because of using app.get('*') request to not existent static files responses with rendered index.ejs file instead of error 404.
Is there any way to fix it without additional conditions in routes?
Just add something like:
app.get(/\/(js|css|img)\/.*/, function (req, res) {
res.send(404);
});
before app.get('*'). Any request to /js that wasn't already matched by the static middleware references an file that does not exist.
Resolved problem by nginx proxying
I have an existing coded frontend i.e views,javascripts,stylesheets (https://github.com/stdrunk/Taskr) and I intend to add this to the express framework so that i can link it to the db.
I added the contents to the public folder. The javascripts in the javascript folder, css in stylesheets, and images in images folder.
Then i changed the code of app.js according to this Render basic HTML view?
Now when run app.js and open the page in the browser i get a stripped version of my original page.
No error comes in the console.
This is my app.js
/**
* Module dependencies.
*/
var express = require('express');
var routes = require('./routes');
var user = require('./routes/user');
var http = require('http');
var path = require('path');
var app = express();
// all environments
app.set('port', process.env.PORT || 3000);
//app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'jade');
app.set('views', __dirname + '/views');
app.engine('html', require('ejs').renderFile);
app.use(express.static(__dirname + '/public'));
app.use(express.favicon());
app.use(express.logger('dev'));
app.use(express.json());
app.use(express.urlencoded());
app.use(express.methodOverride());
app.use(app.router);
app.use(express.static(path.join(__dirname, 'public')));
// development only
if ('development' == app.get('env')) {
app.use(express.errorHandler());
}
app.get('/', routes.index);
app.get('/users', user.list);
app.get('/home', function (req, res)
{
res.render('index.html');
});
http.createServer(app).listen(app.get('port'), function(){
console.log('Express server listening on port ' + app.get('port'));
});
You could put all those dirs under a 'public' dir, and then use:
app.use(express.static(__dirname + '/public'));
That way, express will always just send anything requested from those directories, and you won't need to worry about static files at all.
Although, I do recommend keeping something like Apache running on your server to serve static files. Images especially.
I am using latest version of express no.3 . I have read the docs and did exactly as was written but it is still not working as it suppose to .I get file in my upload dir after submit but then everything stops and callback function from app.post doesn't fire . The code:
HTML-JADE
form(action="/upload", method="post", enctype="multipart/form-data")
input(type="file", name="image")
input(type='submit', value='submit')
App.js
var express = require('express')
, user = require('./routes/user')
, http = require('http')
, path = require('path')
, mongo = require('mongodb')
, Server = mongo.Server
, Db = mongo.Db
, routes = require('./routes')
var app = express();
app.configure(function(){
app.set('port', process.env.PORT || 3000);
app.set('views', __dirname + '/views');
app.set('view engine', 'jade');
app.use(express.favicon());
app.use(express.logger('dev'));
app.use(express.bodyParser({uploadDir:'./upload'}));
app.use(express.methodOverride());
app.use(express.cookieParser('your secret here'));
app.use(express.session());
app.use(app.router);
app.use(require('stylus').middleware(__dirname + '/public'));
app.use(express.static(path.join(__dirname, 'public')));
});
app.post('/upload', function(req, res) {
console.log(req.files.image) // this doesn't fire at all - no matter what i write here
res.send(200) //doesn't run also
});
You need to return a response after reading the data. Without returning a response, express has no idea of when your response is finished and node will not close the connection to the client.
try this:
app.post('/upload', function(req, res) {
console.log(req.files.image);
req.on('data', function(raw) {
console.log('received data');
});
req.on('end', function() {
console.log('end');
res.send(200);
});
}
Try sending a simple response to the user.
app.post('/upload', function(req, res) {
console.log(req.files.image);
res.write('File Uploaded !!');
res.end();
}
Update
You should try changing the format to
app.post('/upload', function(err,req,res,next){
//Check for errors then handle it
}
Can't tell much until I know what errors you are getting, since file is being uploaded to upload dir bodyParser is working fine. Maybe your route is being handled by another function, or not handled at all. app.router is code that calls the callback .
When you do app.get('/upload', function(req, res) { ... }); it is the router that actually invokes the callback function to process the request. Can you confirm if you can do app.get('/upload',...); the html-jade file succesfully. If not then there is a problem in your routes.
Finally I found solution - that was because i used node 0.9.6 -pre. After change to 0.8.21 everything works fine.
Thanks all for your help.
I don't seem to get JSHTML to work as a template engine on Express.js in Node.js. When I install my Express.js application and a basic application is created for me, and I run it I get this error message:
500 TypeError: Property 'engine' of object #<View> is not a function
at View.render (/Users/blackbook/nodejs/ds/node_modules/express/lib/view.js:75:8)
at Function.app.render (/Users/blackbook/nodejs/ds/node_modules/express/lib/application.js:504:10)
at ServerResponse.res.render (/Users/blackbook/nodejs/ds/node_modules/express/lib/response.js:677:7)
at exports.index (/Users/blackbook/nodejs/ds/routes/index.js:7:7)
at callbacks (/Users/blackbook/nodejs/ds/node_modules/express/lib/router/index.js:165:11)
at param (/Users/blackbook/nodejs/ds/node_modules/express/lib/router/index.js:139:11)
at pass (/Users/blackbook/nodejs/ds/node_modules/express/lib/router/index.js:146:5)
at Router._dispatch (/Users/blackbook/nodejs/ds/node_modules/express/lib/router/index.js:173:5)
at Object.router (/Users/blackbook/nodejs/ds/node_modules/express/lib/router/index.js:33:10)
at next (/Users/blackbook/nodejs/ds/node_modules/express/node_modules/connect/lib/proto.js:190:15)
My app.js looks like this (it's what Express.js created for me):
/**
* Module dependencies.
*/
var express = require('express')
, routes = require('./routes')
, http = require('http')
, path = require('path');
var app = express();
app.configure(function(){
app.set('port', process.env.PORT || 3000);
app.set('views', __dirname + '/views');
app.set('view engine', 'jshtml');
app.use(express.favicon());
app.use(express.logger('dev'));
app.use(express.bodyParser());
app.use(express.methodOverride());
app.use(app.router);
app.use(express.static(path.join(__dirname, 'public')));
});
app.configure('development', function(){
app.use(express.errorHandler());
});
app.get('/', routes.index);
http.createServer(app).listen(app.get('port'), function(){
console.log("Express server listening on port " + app.get('port'));
});
I have this installation:
Node.js v.0.8.5
Express.js#3.0.0rc2
jshtml#0.2.3
JSHTML currently works with Express.js 2. There are plans on getting the engine to work with Express.js 3, but currently I am too busy with enjoying the summer! Expect a fix for this problem in the winter!
According to https://github.com/visionmedia/express/wiki/Migrating-from-2.x-to-3.x you can use app.engine for 2-x compatibility.
e.g.
var fs = require("fs");
var jshtml = require("jshtml");
app.engine("jshtml", function (path, options, fn) {
fs.readFile(path, 'utf8', function (err, str) {
if (err) return fn(err);
str = jshtml.compile(str,options)(options).toString();
fn(null, str);
});
});
consolidate.js is used as a bridge between many template engines and express. If your engine isn't supported checkout the source code. Most engines need like 15 lines of code to implement.
I have it working in my project and will probably issue a pull request soon but for now look at my comment in
https://github.com/elmerbulthuis/jshtml/issues/5
Try the following. It works for me, as like you.
Firstly, install jshtml-express via npm and then do the following.
var app = express();
**app.engine('jshtml', require('jshtml-express'));**
// All environments
app.set('port', process.env.PORT || 3000);
app.set('views', __dirname + '/views');
app.set('view engine', 'jshtml');
app.use(express.favicon());
app.use(express.logger('dev'));
app.use(express.bodyParser());
app.use(express.methodOverride());
app.use(app.router);
app.use(express.static(path.join(__dirname, 'public')));
I hope it will work for you as well.