how to upload multiple images from multiple fields from HTML form to node js into two folders then to MongoDB? - html

I have done the first part correctly (upload the images to their folders), but I can't
upload the images to the DB
form.html
the form to upload the images while the user sign up for a new account
<div>
<label for="image">Upload Image</label>
<input type="file" id="image1" name="image1" value="" >
</div><div>
<label for="image">Upload Image</label>
<input type="file" id="image2" name="image2" value="" >
</div>
multer.js
to save the images in the folders
const path = require('path');
const multer = require('multer');
const storage = multer.diskStorage({
destination: (req, file, cb) => {
if (file.fieldname === 'image1') {
cb(null, './logic/uploads');
}
else if (file.fieldname === 'image2') {
cb(null, './logic/uploadp');
}
},
filename: (req, file, cb) => {
cb(null, file.fieldname + '-' + Date.now() + path.extname(file.originalname));
console.log('New image saved!')
}
});
module.exports = multer({ storage: storage });
route
const express = require('express');
const router = express.Router();
const multer = require('../logic/multer')
const { userSignup, userLogin } = require('../logic/Membership_Application');
router.post('/Register',
multer.fields([
{ name: 'image1', maxCount: 1 },
{ name: 'image2', maxCount: 1 },
]),
userSignup
);
router.post('/login', userLogin);
module.exports = router;
logic (data insertion)
const UsersSchema = await new jcs({
name: req.body.name,
email: req.body.email,
phone: req.body.phone,
password: hashedPassword,
nationality: req.body.nationality,
//here is the error(it was working with multer.singel but not with multer,fields)
img: {
data: fs.readFileSync(path.join(__dirname + '/uploads/' + req.file.filename)),
contentType: 'image/png'
},
img2: {
data: fs.readFileSync(path.join(__dirname + '/uploadp/' + req.file.filename)),
contentType: 'image/png'
}
}).save();
model(Database schema)
const db = require('mongoose');
//Database Creation
const UsersSchema = new db.Schema
({
name: { type: String },
email: { type: String },
phone: { type: String },
password: { type: String },
nationality: { type: String },
img:
{
data: Buffer,
contentType: String,
},
img2:
{
data: Buffer,
contentType: String,
},
})
var Users = db.model("Users", UsersSchema);
module.exports = Users;
app.js
const express = require('express');
const app = express();
require('dotenv/config');
const MembershipApplicationRouter = require('./route/Membership_Application');
const AdminRouter = require('./route/admin')
var bodyParser = require('body-parser');
const cors = require('cors');
const db = require('mongoose');
db.connect('mongodb-link',
{
useNewUrlParser: true,
useUnifiedTopology: true
});
const connection = db.connection;
connection.on('connected', () => { console.log("conected with cloud") });
connection.on('error', () => { console.log("error with database") });
app.use('/admin', AdminRouter);
app.use([
bodyParser.urlencoded({ extended: true }),
express.json(),
express.urlencoded({ extended: true })]);
app.use(cors());
app.use('/membershipApplication', MembershipApplicationRouter);
var port = process.env.PORT || 8080;
app.listen(port, () => {
console.log("Server Up and running");
})
module.exports = app;
I have this error msg
New image saved!
New image saved!
C:\Users\abs2\Desktop\m_a_test\logic\Membership_Application.js:79
data: fs.readFileSync(path.join(__dirname + '/uploads/' + req.file.filename)),
^
TypeError: Cannot read properties of undefined (reading 'filename')
at userSignup (C:\Users\abs2\Desktop\m_a_test\logic\Membership_Application.js:79:84)
[nodemon] app crashed - waiting for file changes before starting...

The best practice is to store the file’s location in your server to mongoDB.
So that whenever you to access the file you fetch it’s location then return it back!!

Related

Data is not going in database in MERN

Data is not going in Database in MERN ---
Everything is looking fine and also got status 200 and alert "post created" but data is not going in my database.
How to debug this error. I have tried all solutions. At least tell me the possible reasons for this error. it will help me a lot.
Schema
const mongoose = require("mongoose");
const postSchema = new mongoose.Schema({
title: {
type: String,
required: true,
},
description: {
type: String,
required: true,
},
picture: {
type: String,
required: false,
},
username: {
type: String,
required: true,
},
category: {
type: String,
required: false,
},
createDate: {
type: Date,
default: Date.now,
},
})
const post = new mongoose.model('post', postSchema);
module.exports = post;
server router
const express = require("express");
const router = express.Router();
const post = require("../schema/post-schema");
router.post('/create', async(req,res) => {
try{
console.log(req.body);
const { title, description, picture, username, category, createDate } = req.body;
const blogData = new post({
title:title,
description:description,
picture:picture,
username:username,
category:category,
createDate:createDate
});
console.log("user " + blogData);
const blogCreated = await blogData.save();
if(blogCreated)
{
return res.status(200).json({
message: "blog created successfully"
})
}
console.log("post "+post);
} catch(error){
res.status(500).json('Blog not saved '+ error)
}
})
module.exports = router;
client file
const initialValues = {
title: '',
description: '',
picture: 'jnj',
username: 'Tylor',
category: 'All',
createDate: new Date()
}
const CreateView = () => {
const [post, setPost] = useState(initialValues);
const history = useHistory();
const handleChange = (e) => {
setPost({...post, [e.target.name]:e.target.value});
}
const savePost = async() => {
try {
const {title, description, picture, username, category, createDate} = post;
console.log(post);
const res = await fetch('/create', {
method: "POST",
headers: {
"Content-Type":"application/json"
},
body: JSON.stringify({title, description, picture, username, category, createDate})
})
console.log(post);
console.log("res is "+ res);
if(res.status===200 )
{
window.alert("post created");
console.log(res);
}
}
catch(e){
console.log(`save post error ${e}`);
}
}
const classes = useStyles();
const url = "https://images.unsplash.com/photo-1543128639-4cb7e6eeef1b?ixid=MnwxMjA3fDB8MHxzZWFyY2h8Mnx8bGFwdG9wJTIwc2V0dXB8ZW58MHx8MHx8&ixlib=rb-1.2.1&w=1000&q=80";
return (
<>
<Box className={classes.container}>
<form method="POST">
<img src={url} alt="banner" className={classes.image}/>
<FormControl className={classes.form}>
<AddIcon fontSize="large" color="action" />
<InputBase placeholder="Title" className={classes.textfield} name="title" onChange={(e)=>handleChange(e)}/>
<Button variant="contained" color="primary" onClick={()=>savePost()}>Publish</Button>
</FormControl>
<TextareaAutosize aria-label="empty textarea" placeholder="Write here..." className={classes.textarea} name="description" onChange={(e)=>handleChange(e)}/>
</form>
</Box>
</>
)
}
export default CreateView;
I think problem is you checking status 200 , so your server returning status 200 in anyway as response . You have to check your server side , and check if is returning code 400 or anything else on failure .

nodemailer-express-handlebars | Error: ENOENT: no such file or directory for template !! node.js

I am trying to send a template form node js using nodemailer and express-handlebars but I'm getting the error no such file I have no idea what I'm missing
I'm attaching my index.js down
const express = require('express')
const app = express()
const bodyParser = require('body-parser')
const hb = require('nodemailer-express-handlebars')
app.use(bodyParser.urlencoded({ extended: true }));
app.use(bodyParser.json())
const nodemailer = require('nodemailer');
const { google } = require('googleapis');
const path = require('path');
// These id's and secrets should come from .env file.
const CLIENT_ID = 'the id';
const CLEINT_SECRET = 'the secret';
const REDIRECT_URI = 'uri';
const REFRESH_TOKEN = 'the token';
const oAuth2Client = new google.auth.OAuth2(
CLIENT_ID,
CLEINT_SECRET,
REDIRECT_URI
);
oAuth2Client.setCredentials({ refresh_token: REFRESH_TOKEN });
app.post("/api", async (req,res) => {
try{
const accessToken = await oAuth2Client.getAccessToken();
const transport = nodemailer.createTransport({
service: 'gmail',
auth: {
type: 'OAuth2',
user: 'your [enter image description here][1]emial',
clientId: CLIENT_ID,
clientSecret: CLEINT_SECRET,
refreshToken: REFRESH_TOKEN,
accessToken: accessToken,
},
})
const handlebarOptions = {
viewEngine: {
extName: ".handlebars",
partialsDir: path.resolve(__dirname, "emialTemplate"),
defaultLayout: false,
},
viewPath: path.resolve(__dirname, "emialTemplate"),
extName: ".handlebars",
};
transport.use(
"compile",
hb(handlebarOptions)
);
// the data which we going to send
const mailOptions = {
from: req.body.name + '<ummed.gagrana#gmail.com>',
to: 'ummed.gagrana#gmail.com',
subject: req.body.subject,
text: "From:" + req.body.email + "\n Message:" + req.body.message,
// html: '<h2>From:</h2>'+'<h4>'+req.body.email+"</h4> <br>"+"<h2>Message:</h2>"+'<h4>'+req.body.message+"</h4>",
template: 'comeBack'
};
//sending mail
const result = await transport.sendMail(mailOptions);
// checking the result after sending mail
console.log(result)
res.send({hey:"well done you just paased some data"})
} catch (error) {
console.log(error)
}
})
app.listen(3000, () => {
console.log("server up and running on port 3000")
})
This the code I am not sure what I'm missing I'm a beginner in nodejs so please help
I am attaching my work directory path for help
[]
You got a typo. emialTemplate --> emailTemplate
const handlebarOptions = {
viewEngine: {
extName: ".handlebars",
partialsDir: path.resolve(__dirname, "emailTemplate"),
defaultLayout: false,
},
viewPath: path.resolve(__dirname, "emailTemplate"),
extName: ".handlebars",
};
After that, I would return the following code line to tell the server that the code has been processed as it should have.
return res.send({hey:"well done you just paased some data"})

express js - GET request 404 not found when using sequelize

I am using Sequelize and express.js in server development.
When I try to send GET request for route /files, an error shows:
{
"errors": {
"message": "Not Found",
"error": {
"status": 404
}
}
}
Folder structure
src
-models
-File.js
-routes
-api
-index.js
-files.js
-index.js
-app.js
-sequelize.js
package.json
I am trying to get ALL records from table files
/src/routes/api/files.js
const router = require('express').Router();
const Files = require('../../models/File')
router.get('/files', (req,res) =>
Files.findAll()
.then(data => {
res.sendStatus(200)
})
.catch(err => console.log(err))
);
module.exports = router;
/src/routes/index.js
var router = require('express').Router();
router.use('/api', require('./api'));
module.exports = router;
/src/models/File.js
const Sequelize = require('sequelize');
const DataTypes = Sequelize.DataTypes;
const db = require('../sequelize')
let files = db.define('files', {
id: {
type: DataTypes.UUID,
defaultValue: DataTypes.UUIDV4,
allowNull: false,
primaryKey: true
},
fileName: {
type: DataTypes.STRING
},
});
module.exports = files;
src/sequelize.js
const { Sequelize } = require('sequelize');
const sequelize = new Sequelize('myDb', 'admin', '1234', {
dialect: 'mysql',
logging: false
});
sequelize.sync({alter: true})
module.exports = sequelize;
src/app.js
var http = require('http'),
path = require('path'),
methods = require('methods'),
express = require('express'),
bodyParser = require('body-parser'),
session = require('express-session'),
cors = require('cors'),
passport = require('passport'),
errorhandler = require('errorhandler'),
mongoose = require('mongoose');
const sequelize = require('./sequelize')
sequelize.authenticate()
.then(() => {console.log("connected")}) //printed "connected"
.catch((err) => {console.log(err)})
var isProduction = process.env.NODE_ENV === 'production';
var app = express();
app.use(cors());
app.use(require('morgan')('dev'));
app.use(bodyParser.urlencoded({ extended: false }));
app.use(bodyParser.json());
app.use(require('method-override')());
app.use(express.static(__dirname + '/public'));
app.use(session({ secret: 'conduit', cookie: { maxAge: 60000 }, resave: false, saveUninitialized: false }));
if (!isProduction) {
app.use(errorhandler());
}
if(isProduction){
mongoose.connect(process.env.MONGODB_URI);
} else {
mongoose.connect('mongodb://localhost/conduit');
mongoose.set('debug', true);
}
require('./models/File');
app.use(require('./routes'));
/// catch 404 and forward to error handler
app.use(function(req, res, next) {
var err = new Error('Not Found');
err.status = 404;
next(err);
});
if (!isProduction) {
app.use(function(err, req, res, next) {
console.log(err.stack);
res.status(err.status || 500);
res.json({'errors': {
message: err.message,
error: err
}});
});
}
app.use(function(err, req, res, next) {
res.status(err.status || 500);
res.json({'errors': {
message: err.message,
error: {}
}});
});
var server = app.listen( process.env.PORT || 3000, function(){
console.log('Listening on port ' + server.address().port);
});
Update 1
src/routes/api/index.js
var router = require('express').Router();
router.use('/', require('./users'));
router.use('/files', require('./files'));
router.use(function(err, req, res, next){
if(err.name === 'ValidationError'){
return res.status(422).json({
errors: Object.keys(err.errors).reduce(function(errors, key){
errors[key] = err.errors[key].message;
return errors;
}, {})
});
}
return next(err);
});
module.exports = router;
Edit
In your /api/index.js file you have :
router.use('/files', require('./files'));
So the URL should be: http://localhost:3000/api/files/files
If you want to change the URL to: http://localhost:3000/api/files, in your files.js, you should change to :
router.get('/', (req,res) => // change "/files" to just "/"
Files.findAll()
.then(data => {
res.sendStatus(200)
})
.catch(err => console.log(err))
);

Using multer with nodejs

I am trying to upload a file from my page to node server.
I can see form data are arriving in the router on server.
But no file is saved in upload folder.
What am I doing wrong?
//router unit
const express = require('express');
const router = express.Router();
const multer = require('multer');
const storage = multer.diskStorage({
destination: (req, file, cb) => {
console.log('chegei')
cb(null, "uploads/")
},
filename: (req, file, cb) => {
console.log('chegei2')
cb(null, Date.now() + "-" + file.ogirinalname)
},
});
module.exports = function (page) {
router.post('/SendMsgBase64', async (req, res) => {
var upload = multer({ storage: storage }).single('userFile');
upload(req, res, function (err) {
if (err) {
console.log(err);
return res.send({ "data": "Error uploading file." });
}
return res.send({ "data": "File is uploaded" });
});
return router
}
//app.js unit
const express = require('express')
const app = express()
const server = require('http').Server(app)
const io = require('socket.io')(server)
const WARoutes = require('../routes/WARoutes');
const path = require('path');
const bodyParser = require('body-parser');
app.use(bodyParser.json()); // support json encoded bodies
app.use(bodyParser.urlencoded({ extended: true })); // support encoded bodies
app.use(express.urlencoded({ extended: true }))
app.get('/', (req, res) => {
res.sendFile('/index.html');
})
app.use('/whats', WARoutes(this.page));
//html
<form id="uploadForm">
<input type="file" name="userFile" />
<input type="button" value="Upload Image" onclick="uploadFile();">
<span id="status"></span>
</form>
<script>
uploadFile = () => {
var formData = new FormData();
debugger
var logoImg = $('input[name="userFile"]').get(0).files[0];
formData.append('logo', logoImg);
var objArr = [];
objArr.push({ "id": "123", "name": "luiz" });
//JSON obj
formData.append('objArr', JSON.stringify(objArr));
$.ajax({
url: "/whats/SendMsgBase64",
type: "POST",
processData: false,
contentType: "application/x-www-form-urlencoded",
data: formData,
complete: function (data) {
alert("success");
}
})
};
</script>
According to multer's github page, if you have not created the uploads directory, it may go something wrong.
If this is the case, creating the directory on your own or passing a string value to destination property is the solution for you.
https://github.com/expressjs/multer
Note: You are responsible for creating the directory when providing destination as a function. When passing a string, multer will make sure that the directory is created for you.

node server not returning any response after API request

I am building an API with Node.js, Express, MYSQL and with the help of sequelize. I am using MVC pattern.
The problem I am encountering however is the server cannot send back any http response after request. When sending a post request for example with postman, the request keeps on loading and will terminate after around 2 minutes with COULD NOT GET ANY RESPONSE exception. While this is happening, data is correctly saved in the database.
This is my AuthController user registration method:
'use strict';
// AuthController.js
var express = require('express');
var router = express.Router();
var bodyParser = require('body-parser');
router.use(bodyParser.urlencoded({ extended: false }));
router.use(bodyParser.json());
var jwt = require('jsonwebtoken');
var bcrypt = require('bcryptjs');
const Model = require('../models/index');
const User = Model.sequelize.import('../models/user');
// Register new User.
exports.register = function(req, res) {
var hashedPassword = bcrypt.hashSync(req.body.password, 8);
User.create({
name : req.body.name,
email : req.body.email,
password : hashedPassword
},
function (err, user) {
if (err)
{
return res.status(500).send("There was a problem registering the user. "+err)
}
else{
// create a token
var token = jwt.sign({ id: user._id }, process.env.AUTH0_CLIENT_SECRET, {
expiresIn: 86400 // expires in 24 hours
});
res.status(200).json({ auth: true, token: token });
}
});
};
// App.js
var createError = require('http-errors');
var express = require('express');
var path = require('path');
var cookieParser = require('cookie-parser');
var logger = require('morgan');
const cors = require('cors');
var app = express();
var indexRoutes = require('./routes/index');
var userRoutes = require('./routes/users');
var courseRoutes = require('./routes/courses');
var authRoutes = require('./routes/auth');
// view engine setup
// Currently I am not using view-templates
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'ejs');
app.use(cors());
app.use(logger('dev'));
app.use(express.json());
app.use(express.urlencoded({ extended: false }));
app.use(cookieParser());
app.use(cors()); //enable CORS
app.use(express.static(path.join(__dirname, 'public')));
//User Routes
app.use('/', indexRoutes);
app.use('/api', userRoutes);
app.use('/api', courseRoutes);
app.use('/api/auth', authRoutes);
// catch 404 and forward to error handler
app.use(function(req, res, next) {
next(createError(404));
});
// error handler
app.use(function(err, req, res, next) {
// set locals, only providing error in development
res.locals.message = err.message;
res.locals.error = req.app.get('env') === 'development' ? err : {};
// render the error page
res.status(err.status || 500);
res.render('error');
});
module.exports = app;
//ROUTES
//auth.js
var express = require('express');
var router = express.Router();
//Require Controller Modules
var controller = require('../controllers/AuthController');
//Register new user
router.post('/register', controller.register);
router.get('/user', controller.me);
router.post('/login', controller.login);
router.get('/logout', controller.logout);
module.exports = router;
//User Model
'use strict';
module.exports = (sequelize, DataTypes) => {
var User = sequelize.define('User', {
//id: DataTypes.INTEGER,
name: DataTypes.STRING,
email: {type: DataTypes.STRING, allowNull: false, unique: true, validate: { isEmail: {msg: "Invalid Email"} }},
password: DataTypes.STRING
}, {});
User.associate = function(models) {
// associations can be defined here
};
return User;
};
DB Connection //in models/index.js
'use strict';
var fs = require('fs');
var path = require('path');
var Sequelize = require('sequelize');
var basename = path.basename(__filename);
var env = process.env.NODE_ENV || 'development';
var config = require(__dirname + '/../config/config.json')[env];
var db = {};
const Op = Sequelize.Op;
if (config.use_env_variable) {
var sequelize = new Sequelize(process.env[config.use_env_variable], config);
} else {
var sequelize = new Sequelize(config.database,
config.username,
config.password,
{
host: config.host,
dialect: config.dialect,
operatorsAliases: false,
}
);
//check if connection is established
sequelize
.authenticate()
.then(() => {
console.log('Database Connection has been established successfully.');
})
.catch(err => {
console.error('Unable to connect to the database:', err);
});
}
fs
.readdirSync(__dirname)
.filter(file => {
return (file.indexOf('.') !== 0) && (file !== basename) && (file.slice(-3) === '.js');
})
.forEach(file => {
var model = sequelize['import'](path.join(__dirname, file));
db[model.name] = model;
});
Object.keys(db).forEach(modelName => {
if (db[modelName].associate) {
db[modelName].associate(db);
}
});
db.sequelize = sequelize;
db.Sequelize = Sequelize;
module.exports = db;
I think there is something wrong I am committing or missing out something. I am experiencing this problem when sending POST REQUESTS. Data is saved in mysql table but no response is sent back.
Please assist. Thanks.
Thank you guys for trying to assist. After working around I discovered that problem was with the controller method. The way it was structured was not sending back response after data is persisted in the database.
This is how I recoded my register method in AuthController:
//Old one
// Register new User.
exports.register = function(req, res) {
var hashedPassword = bcrypt.hashSync(req.body.password, 8);
User.create({
name : req.body.name,
email : req.body.email,
password : hashedPassword
},
function (err, user) {
if (err)
{
return res.status(500).send("There was a problem registering the user. "+err)
}
else{
// create a token
var token = jwt.sign({ id: user._id }, process.env.AUTH0_CLIENT_SECRET, {
expiresIn: 86400 // expires in 24 hours
});
res.status(200).json({ auth: true, token: token });
}
//Rewrite:
// Register new User.
exports.register = function(req, res) {
var hashedPassword = bcrypt.hashSync(req.body.password, 8);
User.create({
name : req.body.name,
email : req.body.email,
password : hashedPassword
})
.then(user=>{
// create a token
var token = jwt.sign({ id: user._id }, config.secret, {
expiresIn: 86400 // expires in 24 hours
});
return res.status(200).json({ auth: true, token: token });
}).catch(err=>{
return res.status(500).send("There was a problem registering the user. "+err)
});
};
This worked for me and the code now works as expected.