req.files not working node.js - express - javascript

Hey so I am trying to accept an uploaded file but everytime I call req.files it is considered undefined... Not sure what I am doing wrong...
This is my app.js file:
var express = require('express')
, user = require('./routes/user')
, http = require('http')
, path = require('path')
, mongoose = require('mongoose')
, mongoConnect = mongoose.connect('mongodb://localhost/clothing')
, 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.bodyParser({uploadDir: './public/img'}));
app.use(express.multipart());
app.use(express.methodOverride());
app.use(app.router);
app.use(express.static(path.join(__dirname, 'public')));
app.get('/user', user.user);
app.post('/user', user.userPost);
Then in my routes file I am just calling
req.files
and on the client side I am calling:
form(action="/user", method="post")
label name:
input(type="text", name="name")
label pic:
input(type="file", name="picture", enctype="multipart/form-data")
input(type="submit", value="Add New Clothes Item")

You need to add enctype="multipart/form-data" to the form

Besides what #Jani said, you have an error in your app:
app.use(express.bodyParser({uploadDir: './public/img'}));
app.use(express.multipart());
This basically translates to:
app.use(express.json());
app.use(express.urlencoded());
app.use(express.multipart({uploadDir: './public/img'}));
app.use(express.multipart());
So no need for the last multipart middleware.
Docs:
http://expressjs.com/api.html#bodyParser

Instead of calling express.bodyParser() consider the alternatives mentioned here: https://github.com/senchalabs/connect/wiki/Connect-3.0
In my case, as Connect will remove multipart middleware compatibility, a warning appears every time I start node server.
connect.multipart() will be removed in connect 3.0
visit https://github.com/senchalabs/connect/wiki/Connect-3.0 for alternatives
connect.limit() will be removed in connect 3.0
I've tested connect-multiparty and req.files is initialized fine. https://github.com/andrewrk/connect-multiparty

Related

Serving css with express js

I have been having a lot of trouble with serving css using express js. I finally figured out how, but I'm a bit confused why my new code works, but my old code doesn't. This is my new code that does work:
const express = require('express');
const path = require('path');
const app = express();
const port = process.env.PORT || 5010;
console.log(__dirname)
app.use('/public', express.static('public'));
app.set('views', path.join(__dirname, 'views'))
app.get('/', (req, res) => {
res.sendFile(path.join(__dirname, 'views', 'home.html'));
});
app.listen(port, () => {
console.log(`Server started on port ${port}`);
});
My file system looks like this:
index.js
public
css
home.css
views
home.html
Originally instead of having:
app.use('/public', express.static('public'));
I had:
app.use(express.static(path.join(__dirname, 'public')));
Why does the second version work, but the first one doesn't? What is the purpose of the first parameter in the second version? Also, just in case it makes a difference, I'm coding on replit.com.
When using 1 parameter
app.use(express.static(path.join(__dirname, 'public')));
This code serve files in the "public" subdirectory of the current directory. The URL to access the file at public/css/home.css is : http://localhost/css/home.css
When using 2 parameters
app.use('/public', express.static('public'));
This code also serve files in the "public" subdirectory of the current directory, with a virtual path prefix "/public". So, the URL to access the file at public/css/home.css is : http://localhost/public/css/home.css
We can change the first parameter to anything, for example, if we have :
app.use('/static', express.static('public'));
Then the URL to the same file becomes : http://localhost/static/css/home.css.
You can find more information from the official document here

Express Render not working return error: No default engine was specified and no extension was provided

I'm writing an Express application without a template engine I am using just using HTML as the template engine.
app.set('view engine', 'html');
actually, the whole code was generated using express-generator and I set the view to --no-view Flag and the index URL page runs well but trying another URL like users or any other except the index URL does work all it shows is
No default engine was specified and no extension was provided.
But if I Add the above code app.set('view engine', 'html'); it returns
Error: Cannot find module 'html'. Below are the codes.
var indexRouter = require('./routes/index');
var usersRouter = require('./routes/users');
var addressRouter = require('./routes/address');
var app = express();
app.set('view engine', 'html');
app.use(logger('dev'));
app.use(express.json());
app.use(express.urlencoded({ extended: false }));
app.use(cookieParser());
app.use(express.static(path.join(__dirname, 'public')));
app.use('/', indexRouter);
app.use('/users', usersRouter);
module.exports = app;
And the userRouter user.js
var express = require('express');
var router = express.Router();
/* GET users listing. */
router.get('/', function(req, res, next) {
res.render('index');
});
module.exports = router;
For Home Page
router.get('/', function(req, res, next) {
res.render('index');
});
Can someone please tell what is wrong here.
To serve html you do not need to use the view engine, just use express.static, as you are already using
app.use (express.static (path.join (__ dirname, 'public')));
As #Henrique said, you are already able to render staticHTML. What’s tripping you up is the res.render calls. Those specifically exist to call a template. Switch to res.send and your error should go away.
What I did was with sendFile on the route controller like the userRoute controller
res.sendFile(path.resolve(__dirname,'../public/index.html'));
and I remove the set engine
app.set('view engine', 'html');
But the index page works perfectly without the above tweak.

How can I use Handlebars with Express?

The question is actually not difficult to understand, I do not know how to implement handlebars in Express.
That's what I've already coded:
var express = require('express');
var app = express();
app.get('/', function (req, res, next) {
return res.render('index');
});
Now is my question, how to set handlebars as app engine for express?
Here is the code as I currently use and learned. I have added a note behind every important line so that you understand it well!
var express = require('express');
var app = express();
var handlebars = require('express-handlebars');
app.engine('handlebars', handlebars({ // Here we define what format you will use (That means what's at the end of each file, for example test.handlebars or test.hbs)
defaultLayout: 'main', // That's the name of your template file. In my case it's main.handlebars
layoutsDir: __dirname + '/views/layouts/' // That's the directory where the template file is
}));
app.set('views', path.join(__dirname, 'views')); // Here you give express the information that it has to look at all files that are in the path /views
app.set('view engine', 'handlebars'); // Here you say express that you are using handlebars to build your website
app.get('/home', function (req, res, next) { // That's a simple GET request (This GET request gets triggered when you enter http://localhost/home for example)
return res.render('index'); // Here we render the index.handlebars file (that is in the /views folder)
});

Compressing files (gzip) in express js 4.4.1

I' using express js app as a web server but all static content is unzipped (js and css files). I tried a couple of solutions like using compression https://github.com/expressjs/compression but can't get is working.
Here is the way I'm doing it (only the part relevant for compression usage):
var app = module.exports = express();
// all environments
app.set('port', process.env.PORT || 3000);
app.set('views', __dirname + '/views');
app.set('view engine', 'jade');
app.use(morgan('dev'));
app.use(bodyParser.urlencoded({extended: true}));
app.use(bodyParser.json());
app.use(methodOverride());
app.use(cookieParser());
var cacheTime = 86; // 7 days
app.use(compression());
app.use(express.static(__dirname + '/public',{ maxAge: cacheTime }));
http.createServer(app).listen(app.get('port'), function () {
console.log('Express server listening on port ' + app.get('port'));
});
Express middleware is always processed in order of declaration.
You have this:
app.use(express.static(...));
app.use(compression());
That means that a request is first processed by express.static(), and when it can handle such a request, it will generate a response immediately and the request will never be passed to the compression middleware.
If you swap the order of the middleware, like this:
app.use(compression());
app.use(express.static(...));
All requests will first pass through the compression middleware, which will set up things so responses will get compressed.

Issue with serving images from express.js

I have issues with serving .png image from my express app. I think there is something wrong with the router setup, because it tries to render page rather than serve a static file. The setup is as follows:
// app.js
// Module dependencies
var express = require('express'),
http = require('http'),
path = require('path'),
session = require('./middlewares/session');
// Create server
var app = module.exports = app ? app : express();
app.set('port', process.env.PORT || 3000);
app.set('view engine', 'jade');
app.set('views', __dirname + '/views');
app.set('view options', { layout: true });
app.use(express.static(path.join(__dirname, '../../public')));
app.use(express.favicon());
app.use(express.logger('dev'));
app.use(express.bodyParser());
app.use(express.methodOverride());
app.use(express.errorHandler());
app.use(express.responseTime());
app.use(express.cookieParser());
app.use(app.router);
var routes = require('./routes')(app);
if ('development' == app.get('env')) {
app.use(express.errorHandler());
}
// Start server
http.createServer(app).listen(app.get('port'), function() {
console.log('Express server listening on port ' + app.get('port'));
console.log(__dirname);
});
Then my routes file looks like this:
// routes.js
module.exports = function(app) {
//Routes
// app.get('/', routes.index);
app.get('/api/places', places);
app.get('/add-review', review);
app.get('/logout', logout);
app.get('/:location?/:category?', session(app), routes.index);
}
The jade view where I'm trying to load an image
# view
img(src="/nodeapp/img/logo-white.png")
I'm using reverse proxy for node app which root is this http://app.com/nodeapp
The folder structure:
public
components
css
img
js
server
srs
views
app.js
test
The error that I'm getting is this:
TypeError: Cannot read property 'logo-white.png' of undefined
at Object.get_listings (/app/server/src/models/vendors.js:354:16)
at exports.index (/app/server/src/handlers/index.js:6:31)
at callbacks (/app/node_modules/express/lib/router/index.js:161:37)
at /app/server/src/middlewares/session.js:13:5
at /app/bbe/server/src/api.js:18:3
at _fulfilled (/app/node_modules/requestify/node_modules/q/q.js:798:54)
at self.promiseDispatch.done (/app/requestify/node_modules/q/q.js:827:30)
at Promise.promise.promiseDispatch (/app/node_modules/requestify/node_modules/q/q.js:760:13)
at /app/node_modules/requestify/node_modules/q/q.js:574:44
at flush (/app/node_modules/requestify/node_modules/q/q.js:108:17)
GET /img/logo-white.png 500 857ms
So, here it's trying to actually render my jade views rather than serving from a static folder. Other static files such as js and css are served fine. Why is this happening?
Thanks!
=== Edit (added function that renders views) ===
exports.index = function(req, res) {
res.locals.location = data().get_location(req.params);
res.locals.categories = data().get_categories(res.locals.location);
res.locals.listings = data().get_listings(res.locals.location, req.params.category);
var meta = {
title: "My app",
module: "/nodeapp/js/core/index/main.js"
};
res.render('nodeapp/index', meta);
};
I had trouble myself with setting the 'views' path, so maybe the issue is the same.
I would try to set different view paths for the different sites I had like so (per app)
// site1.js
app.set('views', __dirname + '/views/site1');
// site2.js
app.set('views', __dirname + '/views/site2');
For some reason, it just wouldn't find the views to render. So, I had to set them all back to just '/views' directory, and when I rendered them, I included the extra directory there, and that worked.
I'm thinking if you restructured your directories so this
app.use(express.static(path.join(__dirname, '../../public')));
becomes
app.use(express.static(path.join(__dirname, '/public')));
that it might start working for you. I'm assuming all the other things in your public directories aren't being handled right either. If it's just that png file...check the name, rename it, fiddle with it.

Categories

Resources