I'm using node and express and I'm trying to upload some files and some information with a form. The issue is that when I try to acces to anything in the form from backend it is undefined or empty. When I use req.body it's empty and when I try to use req.files they are undefined so I don't know what to do. This is the code:
routerProgress.post("/home/upload-progress", (req, res) => {
const user_id = req.user.id;
console.log(req.body);
const weight = req.body.weight;
const front = req.files.front;
const from_side = req.files.from_side;
const backwards = req.files.backwards;
let front_id = `${v4()}-${front.file.name}`;
let from_side_id = `${v4()}-${from_side.file.name}`;
let backwards_id = `${v4()}-${backwards.file.name}`;
const date = dateFormat(result.request_date, "yyyy-mm-dd");
from.mv('../../uploads/images', front_id, (req, res) => {
if (err) console.log(err);
else console.log("File Uploaded");
})
from_side.mv('../../uploads/images', from_side_id, (req, res) => {
if (err) console.log(err);
else console.log("File Uploaded");
})
backwards.mv('../../uploads/images', backwards_id, (req, res) => {
if (err) console.log(err);
else console.log("File Uploaded");
})
const newProgress = new Progress ({
user_id,
weight,
front_id,
from_side_id,
backwards_id,
date
})
res.redirect("/home");
});
The console.log is only {} and req.files.name_defined_in_form are undefined.
Here is my app.js
import express from 'express';
const app = express();
import path from 'path';
import sequelize from './db/db.js';
import { fileURLToPath } from 'url';
import flash from 'connect-flash';
import session from 'express-session';
import passport from 'passport';
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
// SERVER CONFIGURATION
const PORT = process.env.PORT || 3000;
app.listen(PORT, () => {
console.log(`Listening at ${PORT}`);
sequelize.sync({ force: false })
.then(() => console.log('Database Connected!'))
.catch(err => console.log(err));
});
// VIEW SETTINGS
app.use(express.static(__dirname + "/public"));
app.set("view engine", "pug");
// app.engine('html', require('ejs').renderFile);
app.set('views', path.join(__dirname, "/public/views"));
// BODYPARSER
app.use(express.urlencoded({ extended: false }));
app.use(express.json());
// EXPRESS SESSION
app.use(session({
secret: 'GymApp',
resave: true,
saveUninitialized: true
}));
// CONNECT FLASH
app.use(flash());
// PASSPORT MIDDLEWARE
import passportConfig from './config/passport.js';
passportConfig(passport);
app.use(passport.initialize());
app.use(passport.session());
// GLOBAL VAR
app.use((req, res, next) => {
res.locals.success_msg = req.flash('success_msg');
res.locals.error_msg = req.flash('error_msg');
res.locals.error = req.flash('error');
next();
});
// ROUTES
import { routerIndex } from './routes/index.js';
import { routerProgress } from './routes/app/progress.js';
import { routerAuthentication } from './routes/authentication.js';
import { routerHome } from './routes/app/home.js'
app.use(routerIndex);
app.use(routerProgress);
app.use(routerAuthentication);
app.use(routerHome);
And here is the form done with pug:
form(class="form add-form space-down" method="POST" enctype="multipart/form-data")
div.title
h1 UPLOAD NEW PROGRESS
div.form-group
label(for="weight") Weight:
input(type="number" name="weight" class="form-control" placeholder="Enter your weight")
div.form-group
label(for="front") Upload a front photo
input(type="file" name="front")
div.form-group
label(for="from_side") Upload a from side photo
input(type="file" name="from_side")
div.form-group
label(for="backwards") Upload a backwards photo
input(type="file" name="backwards")
div.button-container
button(type="submit" class="btn btn-primary btn-color space") Upload
If anyone know what I should do to solve this issue I would be very grateful with him.
In order to access the req.files object, you need to add a specific middleware named express-fileupload that allows this functionality.
Simply run npm i express-fileupload, and then add it to your app.js, like so:
const fileUpload = require('express-fileupload');
app.use(fileUpload());
In your specific app.js, you could add it near your other middleware, such as:
import express from 'express';
const app = express();
import path from 'path';
import sequelize from './db/db.js';
import { fileURLToPath } from 'url';
import flash from 'connect-flash';
import session from 'express-session';
import passport from 'passport';
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
// SERVER CONFIGURATION
const PORT = process.env.PORT || 3000;
app.listen(PORT, () => {
console.log(`Listening at ${PORT}`);
sequelize.sync({ force: false })
.then(() => console.log('Database Connected!'))
.catch(err => console.log(err));
});
// FILE UPLOAD
const fileUpload = require('express-fileupload');
app.use(fileUpload());
// VIEW SETTINGS
app.use(express.static(__dirname + "/public"));
app.set("view engine", "pug");
// app.engine('html', require('ejs').renderFile);
app.set('views', path.join(__dirname, "/public/views"));
// BODYPARSER
app.use(express.urlencoded({ extended: false }));
app.use(express.json());
// EXPRESS SESSION
app.use(session({
secret: 'GymApp',
resave: true,
saveUninitialized: true
}));
// CONNECT FLASH
app.use(flash());
// PASSPORT MIDDLEWARE
import passportConfig from './config/passport.js';
passportConfig(passport);
app.use(passport.initialize());
app.use(passport.session());
// GLOBAL VAR
app.use((req, res, next) => {
res.locals.success_msg = req.flash('success_msg');
res.locals.error_msg = req.flash('error_msg');
res.locals.error = req.flash('error');
next();
});
// ROUTES
import { routerIndex } from './routes/index.js';
import { routerProgress } from './routes/app/progress.js';
import { routerAuthentication } from './routes/authentication.js';
import { routerHome } from './routes/app/home.js'
app.use(routerIndex);
app.use(routerProgress);
app.use(routerAuthentication);
app.use(routerHome);
After installing and implementing the middleware via app.use(), the req.files object should now be accessible, given you are passing the files from your form properly.
Related
I am following the brad Traversy Nodejs Tutorial my server is connected and started also my Mongodb connection is running but localhost keep loading and not responding.
I have checked my URL for mongo connection also the password and username all are correct. I have also allow network access from all sources.
This was perfectly working before but now this keeps loading and loading
my db.js
const mongoose = require("mongoose")
const connectDB = async () => {
try {
const conn = await mongoose.connect(process.env.MONGO_URI, {
useNewUrlParser: true,
useFindAndModify: false,
useUnifiedTopology: true
})
console.log(`MongoDB connected ${conn.connection.host}`)
} catch (err) {
console.error(err)
process.exit(1)
}
}
module.exports = connectDB
my app.js
const express = require("express")
const path = require("path")
const dotenv = require('dotenv')
const morgan = require('morgan')
const exphbs = require('express-handlebars')
const passport = require('passport')
const connectDB = require('./config/db')
const routes = require('./routes/index')
const session = require("express-session")
const MongoDBStore = require('connect-mongodb-session')(session);
const mongoose = require('mongoose')
const methodOverride = require('method-override')
//locad config
dotenv.config({ path: './config/config.env' })
connectDB()
//passport config
require('./config/passport')(passport)
const app = express()
const PORT = process.env.PORT || 5000
//body parser
app.use(express.urlencoded({ extended: false }))
app.use(express.json())
//method override
// Method override
app.use(
methodOverride(function (req, res) {
if (req.body && typeof req.body === 'object' && '_method' in req.body) {
// look in urlencoded POST bodies and delete it
let method = req.body._method
delete req.body._method
return method
}
})
)
//logging
if (process.env.NODE_ENV === 'development') {
app.use(morgan('dev'))
}
//handlebars helpers
const { formatDate, truncate, stripTags, select } = require('./helpers/hbs')
//Hnadlebars
app.engine('.hbs', exphbs({ helpers: { formatDate, truncate, stripTags, select }, defaultLayout: 'main', extname: '.hbs' }));
app.set('view engine', '.hbs');
//sessions
app.use(session({
secret: 'keyboard cat',
resave: false,
saveUnitialized: false,
store: new MongoDBStore({
mongooseConnection: mongoose.connection
})
//cookie: { secure: true }
}))
//set passport middleware
app.use(passport.initialize())
app.use(passport.session())
//set global variable
app.use(function (req, res, next) {
res.locals.user = req.user || null
})
//static folder
app.use('/', express.static(path.join(__dirname, 'public')))
//Routes
app.use('/', routes);
app.use('/auth', require('./routes/auth'));
app.use('/stories', require('./routes/stories'));
//listen
app.listen(PORT, console.log(
`server is running in ${process.env.NODE_ENV} mode on port ${PORT}`
))
my ./routes/index.js
const express = require('express')
const router = express.Router()
const { ensureAuth, ensureGuest } = require('../middleware/auth')
const Story = require('../models/story')
//#desc Login/Landing Page
//#route GET/
router.get('/', ensureGuest, (req, res, next) => {
res.render("login", {
layout: "login"
})
})
//#desc Login/Landing Page
//#route GET/
router.get('/dashboard', ensureAuth, async (req, res, next) => {
console.log(req.user)
try {
const stories = await Story.find({ user: req.user._id }).lean() //plain Js object
res.render("dashboard", {
name: req.user.firstName,
stories
})
} catch (error) {
console.log('Stories error', error)
res.render('error/500')
}
})
module.exports = router
my browser
I have found if you're using middlewares then must call next function at the end this was the reason my page wasn't loading
The error was at //set global variable middleware
I am trying to insert a new record by express and node js using mongoose.
My config is my app.js:
import express from 'express';
import morgan from 'morgan';
import cors from 'cors';
import path from 'path';
const app = express();
// Conexión base de datos
const mongoose = require('mongoose');
const uri = 'mongodb://localhost:27017/marcosgarciatfg';
const options = {useNewUrlParser: true, useCreateIndex: true};
// Or using promises
mongoose.connect(uri, options).then(
/** ready to use. The `mongoose.connect()` promise resolves to mongoose instance. */
() => {
console.log('Conectado a DB');
},
/** handle initial connection error */
err => {
console.log(err);
}
);
app.use('/api', require('./routes/nota.js'));
//Middleware
app.use(morgan('tiny'));
app.use(cors());
app.use(express.json());
app.use(express.urlencoded({ extended: true }));
//app.use(express.static(path.join(__dirname, 'public')));rs
// Rutas
app.get('/', (req, res) => {
res.send('Hello Wooooorld!');
});
And this my nota.js on routes:
import express from 'express';
const router = express.Router();
// importar el modelo nota
import Nota from '../models/nota';
// Agregar una nota
router.post('/nueva-nota', async(req, res) => {
const body = req.body;
try {
console.log('body: ' + body);
const notaDB = await Nota.create(body);
res.status(200).json(notaDB);
} catch (error) {
return res.status(500).json({
mensaje: 'Ocurrio un error',
error
});
}
});
This returns always 200:OK on Postman with empty response and in the console log the body is always undefined. What do I do wrong?
You need to apply express.json() middleware before using routes.
//Middleware
app.use(morgan('tiny'));
app.use(cors());
app.use(express.json());
app.use(express.urlencoded({ extended: true }));
app.use('/api', require('./routes/nota.js'));
I have a different problem in flash messages, and that is whenever i open my login page with flash message it's show a number "1". I don't know what does it mean.
app.js
const express = require('express')
const mongoose = require('mongoose')
const session = require('express-session')
const expressValidator = require('express-validator')
const MongoStore = require('connect-mongo')(session)
const path = require('path')
const passport = require('passport')
const bodyParser = require('body-parser')
const flash = require('connect-flash')
const routes = require('./routes/index')
const errorHandlers = require('./handlers/errorHandlers')
require('./handlers/passport')
const app = express();
app.use(express.static(path.join(__dirname + '/public')))
app.set('views', path.join(__dirname, 'public'))
app.engine('html', require('ejs').renderFile)
app.set('view engine', 'ejs')
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
app.use(expressValidator());
// populates req.cookies with any cookies that came along with the request
//app.use(cookieParser());
app.use(session({
secret: process.env.SECRET,
key: process.env.KEY,
resave: false,
saveUninitialized: false,
store: new MongoStore({ mongooseConnection: mongoose.connection })
}));
app.use(passport.initialize());
app.use(passport.session());
app.use(flash());
app.use((req, res, next) => {
res.locals.msg = req.flash();
res.locals.user = req.user || null;
res.locals.currentPath = req.path;
next();
});
// After allllll that above middleware, we finally handle our own routes!
app.use('/', routes);
// If that above routes didnt work, we 404 them and forward to error handler
app.use(errorHandlers.notFound);
// One of our error handlers will see if these errors are just validation errors
//app.use(errorHandlers.flashValidationErrors);
// done! we export it so we can start the site in start.js
module.exports = app;
userController.js
const mongoose = require('mongoose')
const User = mongoose.model('User')
const promisify = require('es6-promisify')
const { check } = require('express-validator/check')
exports.loginForm = (req, res) => {
res.render('login',{
msg: req.flash('error','welcome in login page')})
;
};
exports.registerForm = (req, res) => {
res.render('signup')
};
exports.aboutUs = (req, res) => {
res.render('about', { title: 'Register' })
};
exports.dash = (req, res) => {
res.render('dashhome', { title: 'Register' })
}
exports.homePage = (req, res) => {
res.render('index')
}
exports.contactForm = (req, res) => {
res.render('contact')
}}
login.ejs
This is my main syntax of ejs for flash message
<% if (msg) { %>
<%=msg %>
<% } %>
I expect the result is 'welcome in login page' but i don't know how i get this output when i open login page and see this result "1" instead of flash message.
You should assign data to req.flash before handling the response then you can pass the instance of the assigned data when rendering the view.
exports.loginForm = (req, res) => {
req.flash('error', 'welcome in login page');
res.render('login',{
msg: req.flash('error')
})
};
Before render the view, You just have to save the local messages using the flash like as below:
request.flash("error","Error Occured");
response.locals.messages = request.flash();
res.render('login',{
msg: req.flash('error')
})
Once you set the local messages, you are able to fetch it. Here messages is the main object which as a key called error. So, at the view you may access it like:
<% if (locals.messages) { %>
<script language="javascript">
alert("<%= messages.error %>");
</script>
<% } %>
You can perform whatever you want under the if condition.
I am using express-validator package to validate requested data.
According to these answer I also did change the order or package declaration and initialization
below is my server.js file
const express = require("express");
const session = require("express-session");
const mongoose = require('mongoose');
const MongoStore = require('connect-mongo')(session);
const path = require('path');
const cookieParser = require("cookie-parser");
const bodyParser = require("body-parser");
const passport = require('passport');
const promisify = require('es6-promisify');
const expressValidator = require('express-validator');
const expressJwt = require("express-jwt");
const error_staus = 404;
const morgan = require('morgan');
const logger = require('./helper/logger');
const routes = require('./routes/index');
let server = "";
const bugsnag = require('bugsnag');
// import our configurations from config/tester.js file
const config = require("./config/tester").get(process.env.NODE_ENV);
require('./helper/passport');
require("./helper/translator");
// create our Express app
const app = express();
// view engine setup
app.set("views", `${__dirname}/views`);
app.set("view engine", "ejs");
// serves up static files from the public folder. Anything in app/ will just be served up as the file it is
app.use(express.static(path.join(__dirname, 'app')));
// Takes the raw requests and turns them into usable properties on req.body
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
// Exposes a bunch of methods for validating data. Used heavily on userController.validateRegister
app.use(expressValidator());
// Sessions allow us to store data on visitors from request to request
app.use(session({
secret: '123456',
key: '99785',
resave: false,
saveUninitialized: false,
store: new MongoStore({ mongooseConnection: mongoose.connection })
}));
app.use(session({
"secret": 'secret12345',
"resave": false,
"saveUninitialized": true
}));
// Passport JS is what we use to handle our logins
app.use(passport.initialize());
app.use(passport.session());
// promisify some callback based APIs
app.use((req, res, next) => {
req.login = promisify(req.login, req);
next();
});
// begin logger
app.use(morgan('dev', {
skip: function (req, res) {
return res.statusCode < 400
}, stream: process.stderr
}));
app.use(morgan('dev', {
skip: function (req, res) {
return res.statusCode >= 400
}, stream: process.stdout
}));
app.use('/', routes);
app.use(function(req, res, next){
logger.error('404 page requested');
res.sendStatus(error_staus);
});
// done! we export it so we can start the site in start.js
module.exports = app;
This is the userController.js
const mongoose = require('mongoose');
const User = mongoose.model('User');
const promisify = require('es6-promisify');
exports.loginForm = (req, res) => {
res.render('login', { title: 'Login' });
};
exports.registerForm = (req, res) => {
res.render('register', { title: 'Register' });
};
exports.validateRegister = (req, res, next) => {
req.sanitizeBody('name');
req.checkBody('name', 'You must supply a name!').notEmpty();
req.checkBody('email', 'That Email is not valid!').isEmail();
req.sanitizeBody('email').normalizeEmail({
gmail_remove_dots: false,
remove_extension: false,
gmail_remove_subaddress: false
});
req.checkBody('password', 'Password Cannot be Blank!').notEmpty();
req.checkBody('password-confirm', 'Confirmed Password cannot be blank!').notEmpty();
req.checkBody('password-confirm', 'Oops! Your passwords do not match').equals(req.body.password);
const errors = req.validationErrors();
if (errors) {
req.flash('error', errors.map(err => err.msg));
res.render('register', { title: 'Register', body: req.body, flashes: req.flash() });
return; // stop the fn from running
}
next(); // there were no errors!
};
Note : I am using express-validator version 3.1.2
When I check request object, in that object there is all methods of express-validator too.
But try to use that method I am getting req.checkBody is not a function error.
Can anybody help with these issue ?
I'm trying to use the express session middleware in a separate route handler but the compiler complains that the property 'session' does not exist on type 'Request'.
app.ts
import debug = require('debug');
import express = require('express');
import path = require('path');
import db = require('diskdb');
import bodyParser = require('body-parser');
import session = require('express-session');
import fileStore = require('session-file-store');
import routes from './routes/index/index';
import users from './routes/user';
import register from './routes/users/register';
import login from './routes/users/login';
var app = express();
//Setup sesssion middleware
var sessionFileStore = fileStore(session);
app.use(session({
name: 'server-session-cookie-id',
secret: 'my express secret',
saveUninitialized: true,
resave: true,
store: new sessionFileStore()
}));
//Here we are configuring express to use body-parser as middle-ware.
app.use(bodyParser.urlencoded({ extended: false }));
app.use(bodyParser.json());
// view engine setup
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'pug');
app.use(express.static(path.join(__dirname, 'public')));
app.use('/', routes);
app.use('/users', users);
app.use('/register', session, register);
app.use('/login', session, login);
// catch 404 and forward to error handler
app.use(function (req, res, next) {
var err = new Error('Not Found');
err['status'] = 404;
next(err);
});
// error handlers
// development error handler
// will print stacktrace
if (app.get('env') === 'development') {
app.use((err: any, req, res, next) => {
res.status(err['status'] || 500);
res.render('error', {
message: err.message,
error: err
});
});
}
// production error handler
// no stacktraces leaked to user
app.use((err: any, req, res, next) => {
res.status(err.status || 500);
res.render('error', {
message: err.message,
error: {}
});
});
app.set('port', process.env.PORT || 3000);
var server = app.listen(app.get('port'), function () {
debug('Express server listening on port ' + server.address().port);
});
login.ts
import express = require('express');
import path = require('path');
import bcrypt = require('bcrypt');
const router = express.Router();
router.get('/', (req: express.Request, res: express.Response) => {
res.render(path.join(__dirname, 'login'), { message: 'display login form', username: '' });
});
router.post('/', (req: express.Request, res: express.Response) => {
var un = req.body.username;
var pw = req.body.password;
var db = require('diskdb');
db = db.connect('db', ['users']);
var existing = db.users.findOne({ username: un });
var all = db.users.find();
bcrypt.compare(pw, existing != null ? existing.password : '', function (err, hashres) {
// res == true
if (hashres) {
res.render(path.join(__dirname, 'login'), {
message: ('handle login form submission for ' + un),
username: un,
result: "the username " + un + " is now logged in.",
resulttype: "success"
});
req.session.user = un;
}
else {
res.render(path.join(__dirname, 'login'), {
message: ('handle login form submission for ' + un),
username: un,
result: "the username and password combination is incorrect.",
resulttype: "error"
});
}
});
});
export default router;
All the examples I've found online say that this is supposed to work, though most don't use a separate file for the route hander...
In your app.ts replace these lines of code
app.use('/register', session, register);
app.use('/login', session, login);
to
app.use('/register', register);
app.use('/login', login);
updated:
try update your code of setup session store by this example
var session = require('express-session');
var FileStore = require('session-file-store')(session);
app.use(session({
store: new FileStore(options),
...
}));
if still not work, express-session has a default session store, use the default session store and check if there still a compiler error.
On a hunch I tried to create the same project without TypeScript and it worked. Once I knew that TS was the culprit it was quite straight forward to find that I had to import an additional node package: #types/express-session