Nodejs how to use Multer on function - node.js

I have created controller, routes and functions base api. What issue I am getting is how can I use Multer on function.
I have function like this
const { Users } = require('../models/user');
const { Company } = require('../models/company');
const { Jobs } = require('../models/job');
var mongoose = require('mongoose');
const multer = require('multer');
const FILE_TYPE_MAP = {
'image/png': 'png',
'image/jpeg': 'jpeg',
'image/jpg': 'jpg'
};
const storage = multer.diskStorage({
destination: function (req, file, cb) {
const isValid = FILE_TYPE_MAP[file.mimetype];
let uploadError = new Error('invalid image type');
if (isValid) {
uploadError = null;
}
cb(uploadError, 'public/uploads');
},
filename: function (req, file, cb) {
const fileName = file.originalname.split(' ').join('-');
const extension = FILE_TYPE_MAP[file.mimetype];
cb(null, `${fileName}-${Date.now()}.${extension}`);
}
});
const uploadOptions = multer({ storage: storage });
const createJob = function async(req, res) {
const job = new Jobs({
jobTitle: req.body.jobTitle,
jobDescription: req.body.jobDescription,
jobImage: req.body.userType,
jobType: req.body.jobType,
jobNumberOfPeople: req.body.jobNumberOfPeople,
jobHireTime: req.body.jobHireTime,
jobMinPay: req.body.jobMinPay,
jobMaxPay: req.body.jobMaxPay,
jobday: req.body.jobday,
jobRecieveApplication: req.body.jobRecieveApplication,
jobSubmitResume: req.body.jobSubmitResume,
jobApplicationDeadline: req.body.jobApplicationDeadline,
jobCommunationSetting: req.body.jobCommunationSetting,
jobMessageSetting: req.body.jobMessageSetting,
companyID: req.body.companyID,
});
try {
const jobsave = await job.save();
res.status(200).json({ success: true, data: jobsave })
} catch (err) {
if (err.name === 'ValidationError') {
console.error(Object.values(err.errors).map(val => val.message))
return res.status(400).json({ success: false, message: Object.values(err.errors).map(val => val.message)[0] })
}
res.status(400).json({ success: false, message: err })
}
};
module.exports = { createJob };
and routes like this
const express = require('express');
const router = express.Router();
const userController = require('../controllers/user');
const jobController = require('../controllers/jobs');
router.post('/createJob', jobController.createJob);
module.exports = router;
now I need to add uploadOptions.single('jobImage') in function
I am doing like this const createJob =
const createJob = uploadOptions.single('jobImage'), async(req, res) => { };
Its showing this error on comma don't know why
Its working directly on router but I need to do In function

You can use this:
module.exports = {
createJob : [ uploadOptions.single('jobImage'), createJob ]
};

Related

req is "undefined" in one middleware and not in another

I am trying to use sharp in my MERN application, I sent a request from my frontend and it is undefined in my sharp middleware but if I get rid of the sharp middleware the req is defined later on. If I log the request in createCountry, the body is defined, if I log it in convertToWebP, it is not.
the route is the one that says "/new" below:
const express = require("express");
const router = express.Router();
const { storage } = require("../imageupload/cloudinary.js");
const multer = require("multer");
const {
getCountry,
createCountry,
getCountries,
updateCountry,
deleteCountry,
getAllCountries,
} = require("../controllers/country.js");
const {convertToWebP} = require('../middlewares/toWebP')
const { isLoggedIn, authorizeCountry, validateCountry } = require("../middlewares/auth");
const catchAsync = require("../utils/catchAsync");
const ExpressError = require("../utils/ExpressError");
const upload = multer({ storage: storage });
router.get("/", getCountries);
router.get('/getAll', getAllCountries);
router.post("/new", isLoggedIn, converToWebP, upload.array("images"), createCountry);
router.get("/:countryId", getCountry);
router.patch("/:countryId", validateCountry, authorizeCountry, upload.array("images", 8), updateCountry);
router.delete("/:countryId", authorizeCountry, deleteCountry);
module.exports = router;
the code for create country is here:
exports.createCountry = async (req, res) => {
const { name, description, tags, location, cjLink } = req.body;
const creator = req.user._id;
const images = req.files.map((file) => {
return { image: file.path, publicId: file.filename };
});
try {
const geoData = await geocoder
.forwardGeocode({
query: req.body.location,
limit: 1,
})
.send();
const geometry = geoData.body.features[0].geometry;
const country = new Country({
name,
description,
tags,
creator,
location, //: //geometry
geometry,
url: '',
cjLink: cjLink,
});
const overall = new Overall({
name,
description,
tags,
creator,
location, //: //geometry
geometry,
url: '',
cjLink: cjLink,
});
country.images.push(...images);
country.headerImage.push(...images);
const data = await country.save();
overall.url = `/country/${data._id}`
data.url = `/country/${data._id}`
overall.save();
data.save();
return res.status(201).json(data);
} catch (error) {
return console.log("error during create country", error);
}
};
And lastly the code for the convertToWebP is here:
const sharp = require("sharp");
const { cloudinary } = require("../imageupload/cloudinary");
exports.convertToWebP = async (req, res, next) => {
try {
req.files = await Promise.all(req.files.map(async (file) => {
const buffer = await sharp(file.buffer)
.toFormat('webp')
.toBuffer();
return { ...file, buffer, originalname: `${file.originalname}.webp` };
}));
next();
} catch (error) {
res.status(500).json({ message: error.message });
}
};
Any help is appreciated! I tried console.log as described above, I tried to change the order of the middleware and that does not work either, and I tried logging the req.body directly from the route and it came up as an empty object
You cannot acces req.files before you use multer middleware
You have to reorder
router.post("/new", isLoggedIn, upload.array("images"), converToWebP, createCountry);

postman not working while performing get and post method in nodejs

postman stuckplease check the code if any mistake i did because in postman while sending the post request ,im not getting any response , it is only showing sending request .
Mongodb also connected .
this is my index.js code , please help me out of this
process.env.TZ = 'Asia/Calcutta';
var port = process.env.PORT || 5000;
var cCPUs = require('os').cpus().length;
const cluster = require('cluster');
const express = require('express');
const reader = require('xlsx');
const path = require('path');
const app = express();
const multer = require('multer');
const mongoose = require('mongoose');
const db = require('./Config/Keys').mongoURI;
const logger = require('./Config/workerlog');
const myrecord = require('./model/myrecord');
mongoose
.connect(db, {
keepAlive: true,
})
.then(() => logger.info('MongoDB Connected'))
.catch((err) => console.log(err));
var storage = multer.diskStorage({
filename: function (req, file, cb) {
var datetimestamp = Date.now();
cb(
null,
file.fieldname +
'-' +
datetimestamp +
'.' +
file.originalname.split('.')[file.originalname.split('.').length - 1]
);
},
});
var uploads = multer({
storage: storage,
fileFilter: function (req, file, callback) {
//file filter
if (
['xls', 'xlsx', 'csv'].indexOf(
file.originalname.split('.')[file.originalname.split('.').length - 1]
) === -1
) {
return callback(new Error('Wrong extension type'));
}
callback(null, true);
},
}).single('file');
app.post('/Getexcelfile', async function (req, res) {
uploads(req, res, async function (err) {
if (err) {
return res.status(404).json({ Message: 'Something went to wrong...!' });
}
if (!req.file) {
return res.status(404).json({ Message: 'Please Choose file' });
}
try {
const file = reader.readFile(`${req.file.path}`);
var data = [];
try {
var sheets = file.SheetNames;
for (let i = 0; i < sheets.length; i++) {
const temp = reader.utils.sheet_to_json(
file.Sheets[file.SheetNames[i]]
);
temp.forEach((res) => {
data.push(res);
});
}
} catch (e) {}
await record.insertMany(req.body.BulkData).then((res) => {
res.json({
path: req.file.path,
test: data,
});
res.json(ress);
});
} catch (e) {}
});
});
app.get('/GetRecordDetails', async (req, res) => {
myrecord.find().then((ResponseData) => {
res.json(ResponseData);
});
});
if (cluster.isMaster) {
// Create a worker for each CPU
for (var i = 0; i < cCPUs; i++) {
cluster.fork();
}
} else {
app.listen(port, () => console.log(`Listening on port ${port}`));
}
want to perform get and post in postman . please check the code and help me to solve the problems

How to perform an HTTP post request using express on Cloud Functions for Firebase using busboy

Hi I am trying to insert data in the database using a POST Request but the data is not being inserted.
On further investigation I found that to upload form-data, busboy needs to be used for image upload in firebase functions but I am not able to find a solution for using busboy with post method.
Hence if someone can please help me resolve this issue.
Below is the code for reference.
app.js
const express = require('express')
//const router = true;
const router = new express.Router()
const userInfo = require('../models/userProfile')
const multer = require('multer');
var fs = require('fs');
var path = require('path');
var JSONStream = require('JSONStream');
const planCheck = require('../models/planDetails');
const login = require('../models/login_creditionals');
const {Storage} = require('#google-cloud/storage');
const {format} = require('util');
const busboy = require('busboy');
const storage = new Storage({
projectId: "biz-1",
keyFilename: "/Users/akm/pixNodes/functions/pixbiz-65a402.json"
});
const bucket = storage.bucket("gs://biz-1");
const upload = multer({
storage: multer.memoryStorage(),
limits: {
fileSize: 10 * 1024 * 1024
}
})
const uploadImageToStorage = (file) => {
return new Promise((resolve, reject) => {
if (!file) {
reject('No image file');
}
let newFileName = `${Date.now() + path.extname(file.originalname)}`;
let fileUpload = bucket.file(newFileName);
const blobStream = fileUpload.createWriteStream({
metadata: {
contentType: file.mimetype
}
});
blobStream.on('error', (error) => {
reject('Something is wrong! Unable to upload at the moment.');
});
blobStream.on('finish', () => {
// The public URL can be used to directly access the file via HTTP.
const url = format(`https://storage.googleapis.com/${bucket.name}/${fileUpload.name}`);
resolve(url);
});
blobStream.end(file.buffer);
});
}
router.post('/userprofile/check' ,upload.single('profile_pic'), async (req,res) => {
var reqFiles;
var reqFilesUrl;
reqFiles = req.file;
if(reqFiles) {
// const imagerUrl = await uploadImageToStorage(reqFiles)
reqFilesUrl = imagerUrl;
console.log(reqFilesUrl);
const notify = new userInfo({
userId: req.body.userId,
mobile_number : req.body.mobileNumber,
profile_pic: reqFilesUrl
})
try {
console.log('success insert data');
await notify.save((err,post) => {
if(err) {
console.log(err);
}
//console.log('data saved', post);
res.status(201).send(post);
});
// });
// res.status(201).send();
console.log('201');
} catch(e) {
//res.status(401);
return res.send(e);
}

The link to go to the `ejs` page does not work

I can't go to another ejs page.
Description
The link to go to the ejs page does not work
I have an existing project... Everything works in it...
Example: a transition is made from Index -> to a subpage.
In the current state of the project, the subpage is located at localhost:3000/0/articles/14
The subpage is filled with data from the database.
I did.
created my own Index page;
Index page- opens;
created my own About Subpage;
Result: switching from the Index page to About does not work.
Index.ejs
<h1>Index page</h1>
<a href="/about" >About-1. Описание</a> </br>
<a href="http://localhost:3000/About/" >About-2. Описание</a>
I added to the file routes.js
.get('/about', (req, res) => {
res.render('about');
})
The whole code routes.js
const multer = require('multer');
const rand = require('randomstring');
const filesStorage = multer.diskStorage({
destination: (req, file, next) => {
next(null, 'static/uploads/files');
},
filename: (req, file, next) => {
const ext = file.originalname.split('.').pop();
next(null, rand.generate({
length: 32,
charset: 'alphabetic'
}) + '.' + ext);
}
});
const filesUpload = new multer({
storage: filesStorage
});
const site = {
main: require('./controllers/main')
};
const cms = {
articles: require('./controllers/cms/articles'),
files: require('./controllers/cms/files'),
lang: require('./controllers/cms/lang'),
slideshow: require('./controllers/cms/slideshow')
};
module.exports = (app, passport) => {
app
.get('/', site.main.lang)
.get('/video', site.main.video)
.get('/slideshow', site.main.slideshow)
.get('/:lang', site.main.index)
/*articles*/
.get('/:lang/articles', site.main.index)
.get('/:lang/articles/:id', site.main.article)
.get('/:lang/panomuseum', site.main.panomuseum)
.get('/:lang/panomuseum/2', site.main.panomuseum2)
.get('/:lang/panotheatre', site.main.panotheatre)
/*My*/
// .get('/:lang/articles', site.main.index)
.get('/Index', site.main.index)
.get('/history', site.main.history)
// .get('/history', (req, res) => {
// res.render('history');
// })
.get('/about', (req, res) => {
res.render('about');
})
;
app
.get('/cms/lang', cms.lang.index)
.post('/cms/lang', filesUpload.any(), cms.lang.save)
.get('/cms/:lang/articles', cms.articles.index)
.post('/cms/articles/saveOrder', cms.articles.saveOrder)
.get('/cms/:lang/articles/add', cms.articles.add)
.post('/cms/:lang/articles/add', filesUpload.any(), cms.articles.postAdd)
.get('/cms/:lang/articles/:id/edit', cms.articles.edit)
.post('/cms/:lang/articles/:id/edit', filesUpload.any(), cms.articles.postEdit)
.get('/cms/:lang/articles/:id/delete', cms.articles.delete)
.get('/cms/:lang/articles/:id', cms.articles.subArticle)
.get('/cms/:lang/articles/add/:id', cms.articles.add)
.post('/cms/files/delete', cms.files.delete)
.post('/cms/files/saveFile', filesUpload.single('file'), cms.files.saveFile)
.post('/cms/files/saveThumb', filesUpload.single('thumb'), cms.files.saveThumb)
.get('/cms/slideshow', cms.slideshow.index)
.post('/cms/slideshow/save', filesUpload.any(), cms.slideshow.save);
return app;
controllers\main.js
const db = require('../db');
const fs = require('fs');
const path = require('path');
const config = require('../config.js');
class Main {
async video(req, res, next) {
const videoFolder = './static/video'
let videos = []
fs.readdirSync(videoFolder).forEach((file) => {
let extension = path.extname(file)
let filename = path.basename(file, extension)
videos.push({
file,
filename: parseInt(filename),
})
})
videos = videos.sort((a, b) => {
return a.filename - b.filename
})
return res.render('video', {
domain: config.express.domain,
videos,
})
}
async panomuseum(req, res) {
const article = await db.article.getByID(req.params.lang);
const sub = await db.article.getRoot(req.params.lang);
const files = await db.files.getByOwnerId(req.params.lang);
const lang = await db.lang.getById(req.params.lang);
return res.render('panomuseum', {
article,
sub,
files,
lang
});
}
async panomuseum2(req, res) {
const article = await db.article.getByID(req.params.lang);
const sub = await db.article.getRoot(req.params.lang);
const files = await db.files.getByOwnerId(req.params.lang);
const lang = await db.lang.getById(req.params.lang);
return res.render('panomuseum2', {
article,
sub,
files,
lang
});
}
async panotheatre(req, res) {
const article = await db.article.getByID(req.params.lang);
const sub = await db.article.getRoot(req.params.lang);
const files = await db.files.getByOwnerId(req.params.lang);
const lang = await db.lang.getById(req.params.lang);
return res.render('panotheatre', {
article,
sub,
files,
lang
});
}
async index(req, res) {
const article = await db.article.getByID(req.params.lang);
const sub = await db.article.getRoot(req.params.lang);
const files = await db.files.getByOwnerId(req.params.lang);
const lang = await db.lang.getById(req.params.lang);
const timeout = await db.settings.getByID("timeout");
const caption = await db.settings.getByID("caption");
return res.render("index", {
article,
sub,
files,
lang,
timeout,
caption,
domain: req.app.get("domain"),
});
}
// async history(req, res) {
// // const article = await db.article.getByID(req.params.lang);
// // const sub = await db.article.getRoot(req.params.lang);
// // const files = await db.files.getByOwnerId(req.params.lang);
// // const lang = await db.lang.getById(req.params.lang);
// // const timeout = await db.settings.getByID("timeout");
// // const caption = await db.settings.getByID("caption");
// return res.render("history", {
// domain: req.app.get("domain")
// });
// }
async history(req, res) {
console.log('Request for history page recieved');
return res.render("history");
}
async about(req, res) {
console.log('Request for about page recieved');
return res.render("about");
}
async menu(req, res) {
return res.render("menu", {
domain: req.app.get("domain"),
});
}
async slideshow(req, res) {
const slideshow = await db.files.getSlideshow();
const timer = await db.settings.getByID("timer");
return res.render("slideshow", {
slideshow,
timer,
domain: req.app.get("domain"),
});
}
async slide(req, res) {
const slideshow = await db.files.getByID(req.params.id);
const timer = await db.settings.getByID("timer");
return res.render("slideshow", {
slideshow: [slideshow],
timer,
domain: req.app.get("domain"),
});
}
async article(req, res) {
const article = await db.article.getByID(req.params.id);
const sub = await db.article.getSub(req.params.id);
const files = await db.files.getByOwnerId(req.params.id);
const id = req.params.id;
const lang = await db.lang.getById(req.params.lang);
const timeout = await db.settings.getByID("timeout");
const caption = await db.settings.getByID("caption");
return res.render("index", {
id,
article,
sub,
files,
lang,
timeout,
caption,
domain: req.app.get("domain"),
});
}
async lang(req, res) {
const langs = await db.lang.getAll();
let activeCount = 0;
for (let lang of langs) {
if (lang.value == 1) {
activeCount++;
}
}
if (activeCount == 0) {
return res.redirect("/0");
} else if (activeCount == 1) {
for (let lang of langs) {
if (lang.value == 1) {
return res.redirect("/" + lang.id);
}
}
}
const timeout = await db.settings.getByID("timeout");
return res.render("lang", {
langs,
timeout,
});
}
async openSlide(req, res) {
console.log("openSlide");
let files = await db.files.getSyncSmartHome();
parentIO.sockets.in("client").emit("goToUrl", {
message: "/slide/" + files[parseInt(req.params.id)].id,
});
return res.json({
success: true,
});
}
async openSlideshow(req, res) {
console.log("open slideshow");
parentIO.sockets.in("client").emit("goToUrl", {
message: "/slideshow",
});
return res.json({
success: true,
});
}
}
module.exports = new Main();

How to upload file using Koa?

I am setting up a new server and want to support advanced upload function. Firstly I need to validate file (filetype, filesize, maxcount), and finally upload it to some destination. I tried something with koa-multer but I cannot get multer validation errors.
multer.js
const multer = require('koa-multer')
const storage = multer.diskStorage({
destination: function (req, file, cb) {
cb(null, './public/uploads/')
},
filename: function (req, file, cb) {
var fileFormat = (file.originalname).split('.')
cb(null, file.fieldname + '_' + Date.now() + '.' + fileFormat[fileFormat.length - 1])
}
})
const fileFilter = (req, file, cb) => {
if (file.mimetype === 'image/jpeg' || file.mimetype === 'image/png') {
cb(null, true)
} else {
cb(new Error('This is not image file type'), false)
}
}
const upload = multer({
storage: storage,
limits: {
fileSize: 1024 * 1024 * 1,
files: 5
},
fileFilter: fileFilter
})
module.exports = upload
router.js
const Router = require('koa-router')
const multer = require('../middlewares/multer')
const auth = require('../middlewares/auth')
const controller = require('../controllers').userController
const schemas = require('../schemas/joi_schemas')
const validation = require('../middlewares/validation')
const router = new Router()
const BASE_URL = `/users`
router.post(BASE_URL, auth , validation(schemas.uPOST, 'body'), controller.
addUser)
router.put(`${BASE_URL}/:id`, auth , multer.single('logo')(ctx, (err) => {
if (err) {
ctx.body = {
success: false,
message: 'This is not image file'
}
}
}), controller.editUser)
router.delete(`${BASE_URL}/:id`, auth , controller.deleteUser)
module.exports = router.routes()
How can I solve upload problem this in best way for long term maintain of code?
The simplest approach for uploading files is the following (assume the form has a file upload field called avatar:
const Koa = require('koa')
const mime = require('mime-types')
const Router = require('koa-router')
const koaBody = require('koa-body')({multipart: true, uploadDir: '.'})
const router = new Router()
router.post('/register', koaBody, async ctx => {
try {
const {path, name, type} = ctx.request.files.avatar
const fileExtension = mime.extension(type)
console.log(`path: ${path}`)
console.log(`filename: ${name}`)
console.log(`type: ${type}`)
console.log(`fileExtension: ${fileExtension}`)
await fs.copy(path, `public/avatars/${name}`)
ctx.redirect('/')
} catch(err) {
console.log(`error ${err.message}`)
await ctx.render('error', {message: err.message})
}
})
Notice that this example uses Async Functions which allows for clean code with a standard try-catch block to handle exceptions.
koa middleware is like a nested callback, you should catch "next()" not after multer
router.put(`${BASE_URL}/:id`, auth , async (ctx, next) => {
try{
await next()
} catch(err) {
ctx.body = {
success: false,
message: 'This is not image file'
}
}
}, multer.single('logo'), controller.editUser)
but you do this, it will catch controller.editUser errors too which not been caught by controller itself.
You can use one of two options:
The first is by adding callback function to the end of the route.
const multer = require('#koa/multer')
//Options to limit file size and file extension
const upload = multer({
dest: '../avatars',
limits: {
fileSize: 1024*1024
},
fileFilter(ctx, file, cb) {
if (!file.originalname.match(/\.(jpg|jpeg|png)$/)) {
return cb(new Error('Please upload a World document'))
}
cb(undefined, true)
}
})
//The last callback should handle the error from multer
router
.post('/upload', upload.single('upload'), async (ctx) => {
ctx.status = 200
}, (error, ctx) => {
ctx.status = 400
ctx.body = error.message
})
})
The second option is by adding try/ catch before calling multer middleware:
router
.post('/upload', async (ctx, next) => {
try {
await next()
ctx.status = 200
} catch (error) {
ctx.status = 400
ctx.body = error.message
}
}, upload.single('upload'), async ctx => {ctx.status = 200})
In last case if exception will thrown in multer, it will be handled by try/catch in previous await next()

Resources