Trouble with multer and saving mongodb model - javascript

I am using multer to upload a file to my backend. Here is the route:
// #route POST api/users/resume
// #desc Upload user resume
// #access Private
router.post("/resume", auth, async (req, res) => {
try {
let resumeBackupName = null;
let resumeMatrix = {
"application/vnd.ms-excel": "xls",
"application/msword": "doc",
"application/vnd.openxmlformats-officedocument.wordprocessingml.document":
"docx",
"application/pdf": "pdf"
};
let user = await User.findById({ _id: req.user.id.toString() });
if (
user.resume &&
user.resume.extension &&
user.resume.extension.length > 0
) {
resumeBackupName =
req.user.id.toString() +
"-backup-" +
user.resume.extension.length.toString() +
"." +
user.resume.extension[user.resume.extension.length - 1];
user.resume.backup.push(resumeBackupName);
}
let date = new Date();
let resumeMimeType = null;
let resumeExtension = null;
const storage = multer.diskStorage({
destination: (req, file, cb) => {
cb(null, "public");
},
filename: (req, file, cb) => {
cb(
null,
req.user.id.toString() +
"-" +
date.getTime() +
"-" +
file.originalname
);
}
});
const upload = multer({ storage: storage }).single("file");
upload(req, res, err => {
resumeMimeType = req.file.mimetype;
resumeExtension = resumeMatrix[resumeMimeType];
user.resume.mimeType = resumeMimeType;
user.resume.extension.push(resumeExtension);
if (err instanceof multer.MulterError) {
return res.status(500).json(err);
} else if (err) {
return res.status(500).json(err);
}
});
await user.save();
return res.json({ msg: "Success!" });
} catch (err) {
console.log(err);
res.status(500).send("Server error");
}
});
The problem is within the upload function. Console logging user after the user.resume.mimeType = resumeMimeType; and user.resume.extension.push(resumeExtension); lines properly displays the values, but when await user.save() is hit, it doesn't save anything. Is it a scoping issue? I'm getting a warning variables declared but never used for let resumeMimeType = null; and let resumeExtension = null;, but they are used in the upload function. Not sure what I'm doing wrong.

Related

MERN - Getting error: "Cannot read property 'path' of undefined" when trying to upload a pdf file using multer

Like I said on the title, I'm facing that error when I'm trying to upload a file from the client-side. Here are the code blocks for more context:
Route:
const express = require("express");
const { upload } = require("../middlewares/uploadMiddleware");
const { registerResearchSheet } = require("../controllers/researchSheetControllers");
const router = express.Router();
router.route("/").post(upload.single("file"), registerResearchSheet);
Middleware:
const multer = require("multer");
const storage = multer.diskStorage({
destination: function (req, file, cb) {
cb(null, "backend/uploads/");
},
filename: function (req, file, cb) {
cb(
null,
new Date().toISOString().replace(/:/g, "-") + "-" + file.originalname
);
},
});
const fileFilter = (req, file, cb) => {
if (file.mimetype === "application/pdf") {
cb(null, true);
} else {
cb(null, false);
}
};
const upload = multer({ storage: storage, fileFilter: fileFilter });
module.exports = { upload };
Controller:
const asyncHandler = require("express-async-handler");
const ResearchSheet = require("../models/researchSheetModel");
const registerResearchSheet = asyncHandler(async (req, res) => {
const {
title,
director,
coordinator,
students,
reviewers,
proposalType,
investigationType,
status,
} = req.body;
if (!req.file) {
res.status(400);
throw new Error("The file hasn't be uploaded correctly"); **//This is the triggering error**
}
const file = req.file.path;
const researchSheetExists = await ResearchSheet.findOne({ title, students });
if (researchSheetExists) {
res.status(400);
throw new Error("Title or students can't be repeated");
}
const researchSheet = await ResearchSheet.create({
title,
file, // file: buffer,
director,
coordinator,
students,
reviewers,
proposalType,
investigationType,
status,
});
if (researchSheet) {
res.status(201).json({
_id: researchSheet._id,
title: researchSheet.title,
file: researchSheet.file,
director: researchSheet.director,
coordinator: researchSheet.coordinator,
students: researchSheet.students,
reviewers: researchSheet.reviewers,
proposalType: researchSheet.proposalType,
investigationType: researchSheet.investigationType,
status: researchSheet.status,
});
} else {
res.status(400);
throw new Error("An error has ocurred");
}
});
And finally the frontend part:
const [file, setFile] = useState(null);
//code..
const singleFileUpload = (e) => {
setFile(e.target.files[0]);
};
const submitHandler = async (e) => {
e.preventDefault();
const formData = new FormData();
formData.append("title", title);
formData.append("file", file);
formData.append("director", director);
formData.append("coordinator", coordinator);
formData.append("students", students);
formData.append("proposalType", proposalType);
formData.append("investigationType", investigationType);
console.log(file); //This log is correctly showing the File and its properties
if (
!title ||
!coordinator ||
!students ||
!proposalType ||
!investigationType
) {
setMessage("You must fill all the fields");
} else {
dispatch(registerResearchSheetAction(formData));
// history.push("/listresearchsheets");
}
};
//more code...
<Form.Control
className="mb-3"
type="file"
accept=".pdf"
onChange={(e) => singleFileUpload(e)}
/>
<Button type="submit">Register</Button>
Action:
export const registerResearchSheetAction =
(
title,
file,
director,
coordinator,
students,
reviewers,
proposalType,
investigationType,
status
) =>
async (dispatch) => {
try {
dispatch({
type: RESEARCHSHEET_REGISTER_REQUEST,
});
const formData = new FormData();
formData.append("file", file);
formData.append("title", title);
formData.append("director", director);
formData.append("coordinator", coordinator);
formData.append("students", students);
formData.append("reviewers", reviewers);
formData.append("proposalType", proposalType);
formData.append("investigationType", investigationType);
formData.append("status", status);
const config = {
headers: {
"Content-Type": "multipart/form-data",
},
};
const { data } = await axios.post(
"/api/researchsheets",
formData,
config
);
dispatch({ type: RESEARCHSHEET_REGISTER_SUCCESS, payload: data });
} catch (error) {
dispatch({
type: RESEARCHSHEET_REGISTER_FAIL,
payload:
error.response && error.response.data.message
? error.response.data.message
: error.message,
});
}
};
I already tested the functionality on the server-side using Postman and it is uploading, more than the file, the route/path of it successfully on the database. That's why I'm thinking that the problem must be on the client-side. I really don't know what I'm missing here, so that's why I came for a little of help, I hope I was clear on my explanaiton.
Thank you in advance!

Upload images to MongoDB after compressing and delete images from the Multer uploads directory

I am very new to development related work. PLEASE HELP
I am trying to upload 10 images taken from user (implemented via MULTER) to the mongoDB database but, before final upload I want to compress the images using SHARP.
I tried doing this using callbacks. But FAILED.
This is what I want to do:
use MULTER to upload an array of 10 images to the UPLOADS/IMAGES directory.
FOR EACH file in the array use SHARP to compress the file and store the new compressed .jpeg file to UPLOADS/COMPRESSED directory.
THEN
use fsPromises.readFile to read the newly compressed image in the UPLOADS/COMPRESSED directory.
THEN
make an object : const toInsertImgData = { data: result, contentType: "image/jpeg"};
and push it in an array called imgArray. Here result is binary data read in the previous step.
THEN
use fsPromises.unlink to remove all files in UPLOADS/IMAGES and UPLOADS/COMPRESSED
THEN
Use the imgArray to make a document to save in the posts collection of the Database.
Right now every time the imgArray is empty when I want to use it at the end. I know that PROMISES or AYSNC/AWAIT can help. But I am not sure how to implement it.
Please help .
THANKYOU IF YOU HAVE READ THIS FAR
Here is my code:
const promises = [];
app.post("/compose/:id", upload.array("image", 10), (req, res) => {
const id = req.params.id;
const imgArray = [];
const caption = req.body.caption;
const now = new Date();
req.files.forEach((file) => {
const compressedImgPath =__dirname +"/public/uploads/compressed/" +now.getDate() +"-" +(now.getMonth() + 1) +"-" +now.getFullYear() +"-" +now.getTime() +".jpeg";
sharp(file.path)
.resize(640, 480)
.jpeg({
quality: 80,
chromaSubsampling: "4:4:4",
})
.toFile(compressedImgPath)
.then(() => {
fsPromises.readFile(compressedImgPath)
.then((result) => {
const toInsertImgData = {
data: result,
contentType: "image/jpeg",
};
imgArray.push(toInsertImgData);
})
.then(() => {
promises.push(fsPromises.unlink(compressedImgPath));
promises.push(fsPromises.unlink(file.path));
})
.catch((err) => {
console.log(err);
});
});
});
Promise.all(promises)
.then(() => {
User.findById(id, (err, result) => {
if (!err) {
if (imgArray.length > 0) {
console.log("found user:" + id);
const newPost = new Post({
uId: id,
userName: result.name,
timeStamp: "5th August, 2020 at 2:10PM",
caption: caption,
img: imgArray,
});
newPost.save((err) => {
if (!err) {
console.log("post saved in DB");
res.redirect("/users/" + id.toString());
} else {
console.log(err);
}
});
} else {
console.log("array is empty");
}
}
});
})
.catch((err) => {
console.log(err);
});
});
inside for each , you use async call, which means all .then() are guaranteed to be executed before .forEach end,so promises array can be ambiguous.
One easy fix is to use fs.promises inside.then() and not push it to promises.
Below is a very similar use case that might help solve the mentioned question. I have provided the full API route code to understand it better.
var fs = require('fs');
var path = require('path');
const sharp = require('sharp');
const multer = require('multer');
var storage = multer.diskStorage({
destination: (req, file, cb) => {
cb(null, './public/uploads')
},
filename: (req, file, cb) => {
cb(null, file.fieldname + '-' + Date.now())
}
});
var upload = multer({ storage: storage });
app.post('/imageupload', upload.single('image'), async (req, res, next) => {
console.log("Image post request by " + req.user.username);
await sharp('./public/uploads/' + req.file.filename).resize(150, 150)
.rotate()
.png({ quality: 100 }).toFile('./public/uploads/' + req.file.filename + '-thumb');
Member.findOneAndUpdate({ sabhe_id: req.body.sabhe_id },
{
img: {
data: fs.readFileSync(path.join('./public/uploads/' + req.file.filename + '-thumb')),
contentType: 'image/png'
}
}
, function (err) {
if (err) {
console.log(err.message);
}
else {
console.log("Image saved to database " + req.user.username);
fs.unlink('./public/uploads/' + req.file.filename, (err) => {
if (err) {
console.error(err.message);
return
}
});
fs.unlink('./public/uploads/' + req.file.filename + '-thumb', (err) => {
if (err) {
console.error(err.message)
return
}
});
if (req.user.isAdmin) {
res.redirect("/admin")
} else {
res.redirect("/profile");
}
}
}
)
});

Wait for child functions to execute before returning

So I have this script that renames files on Google Drive.
It reads two columns from Google Spreadsheet, containing fileID and filename.
Finds the files with fileId on Google Drive, and renames it with the filename from the sheet.
Everything is working fine. To make it easier and available as a route in an API, I exported it.
The problem is, the main module.exports.rename() function has all these child functions that are being executed. It doesn't wait for the execution and renaming and just returns a response.
It just returns the message "Renamed 1 Files Successfully !", since the counter ctr is initially 1.
I tried to use a boolean variable, set as false. Then set it true in the getSheetandBatchRename(), and added an if statement above return for the main function. But that doesn't work of course.
I think I am missing something fundamental here.
What is the right way to achieve this?
module.exports.rename = async function(req, res) {
const fs = require("fs");
const readline = require("readline");
const { google } = require("googleapis");
// If modifying these scopes, delete token.json.
const SCOPES = [
"https://www.googleapis.com/auth/drive.metadata",
"https://www.googleapis.com/auth/spreadsheets.readonly"
];
// The file token.json stores the user's access and refresh tokens, and is
// created automatically when the authorization flow completes for the first
// time.
const PATH = "./server/components/scripts/renamingTool/";
const TOKEN_PATH = PATH + "token.json";
let taskDone = false;
// Load client secrets from a local file.
fs.readFile(PATH + "credentials.json", (err, content) => {
if (err) return console.log("Error loading client secret file:", err);
// Authorize a client with credentials, then call the Google Drive API.
authorize(JSON.parse(content), getSheetandBatchRename);
});
/**
* Create an OAuth2 client with the given credentials, and then execute the
* given callback function.
* #param {Object} credentials The authorization client credentials.
* #param {function} callback The callback to call with the authorized client.
*/
function authorize(credentials, callback) {
const { client_secret, client_id, redirect_uris } = credentials.installed;
const oAuth2Client = new google.auth.OAuth2(
client_id,
client_secret,
redirect_uris[0]
);
// Check if we have previously stored a token.
fs.readFile(TOKEN_PATH, (err, token) => {
if (err) return getAccessToken(oAuth2Client, callback);
oAuth2Client.setCredentials(JSON.parse(token));
callback(oAuth2Client);
});
}
/**
* Get and store new token after prompting for user authorization, and then
* execute the given callback with the authorized OAuth2 client.
* #param {google.auth.OAuth2} oAuth2Client The OAuth2 client to get token for.
* #param {getEventsCallback} callback The callback for the authorized client.
*/
function getAccessToken(oAuth2Client, callback) {
const authUrl = oAuth2Client.generateAuthUrl({
access_type: "offline",
scope: SCOPES
});
console.log("Authorize this app by visiting this url:", authUrl);
const rl = readline.createInterface({
input: process.stdin,
output: process.stdout
});
rl.question("Enter the code from that page here: ", code => {
rl.close();
oAuth2Client.getToken(code, (err, token) => {
if (err) return console.error("Error retrieving access token", err);
oAuth2Client.setCredentials(token);
// Store the token to disk for later program executions
fs.writeFile(TOKEN_PATH, JSON.stringify(token), err => {
if (err) return console.error(err);
console.log("Token stored to", TOKEN_PATH);
});
callback(oAuth2Client);
});
});
}
async function getSheetandBatchRename(auth) {
try {
const data = await getSheet(auth);
console.log("Number of inventories : " + data.length);
taskDone = true;
} catch (err) {
console.log("getSheetandBatchRename");
console.log(err);
}
}
function updateExt(ext) {
// to solve if ther were some problems
if (ext === "1" || ext === "0" || ext === "2" || ext === " Aula 2")
ext = "jpg";
return ext;
}
function getSheet(auth) {
const sheets = google.sheets({ version: "v4", auth });
return new Promise((resolve, reject) => {
sheets.spreadsheets.values.get(
{
spreadsheetId: "1QV3ZshFNVrPCSvMP1O0KjXTcx5pfQMNuNeFbku-TKm4",
range: "Final!A2:B"
},
async (err, res) => {
if (err) reject(err);
let data = res.data.values;
try {
for (const [i, el] of data.entries()) {
let filename = await getafile(auth, el[0], i);
if (filename !== -1) {
let ext = filename.split(".");
ext = ext[ext.length - 1];
// ext = updateExt(ext);
let newName = el[1] + "." + ext;
await renameafile(auth, el[0], i, newName);
}
}
} catch (err) {
console.log("getSheet");
console.log(err);
reject(err);
}
resolve(data);
}
);
});
}
let ctr = 1;
function getafile(auth, fileId, i) {
if (fileId === -1) return -1;
const drive = google.drive({ version: "v3", auth });
return new Promise((resolve, reject) => {
drive.files.get(
{
fileId: fileId
},
(err, res) => {
if (err) {
reject(err);
}
if (res.status !== 200) {
reject("Status Code : " + res.status);
}
let filename = res.data.name;
// console.log(ctr + "\t" + fileId + "\t" + filename);
ctr++;
resolve(filename);
}
);
});
}
function renameafile(auth, fileId, i, newName) {
const drive = google.drive({ version: "v3", auth });
return new Promise((resolve, reject) => {
drive.files.update(
{
fileId: fileId,
resource: {
name: newName
}
},
(err, res) => {
if (err) {
reject(err);
}
if (res.status !== 200) {
reject("Status Code : " + res.status);
}
let filename = res.data.name;
console.log(i + 1 + "\t" + fileId + "\t" + filename);
resolve(filename);
}
);
});
}
return res.status(200).json({
message: "Renamed " + ctr + " Files Successfully !",
status: 200
});
};
You are using fs.readFile, which is asynchronous, as noted by M1K1O in the comments.
If you're using node 10 or more, You can use fs.promises.readFile and await its result, so it will wait for its return before continuing the execution or your program.

How to get a 404 response with a invalid route parameter in Node.js

I have a node.js API I am working on that has some parameter variables in the URL.
One of the tasks I need to achieve is that when a particular id is not valid (as in the id number does not exist in the sqlite database), is that it returns a 404
Typical url setup is localhost/api/employees/:id/timesheets
What I need to do is when that :id does not exist in the sqlite database, return a 404 however it is returning a 201 no matter what I do at the moment.
Please find my code below from the timesheets endpoint and let me know where I am going wrong, be much appreciated. In a nutshell, let's say employee 200 does not exist (so localhost/api/employees/200/timesheets - I want a 404 on that timesheets endpoint but currently it gives a 200 and is not 404'ing. Note that none of the methods are giving a 404 as required at the moment in the below code
Thanks
const express = require('express');
const timesheetsRouter = express.Router({mergeParams: true});
const sqlite3 = require('sqlite3');
const db = new sqlite3.Database(process.env.TEST_DATABASE || './database.sqlite');
timesheetsRouter.param('id', (req, res, next, id) => {
req.id = id;
console.log('doing name validations on ' + id);
db.get('Select * from Timesheet where employee_id = $id', {$id: id}, (error, timesheet) => {
if (error) {
next(error);
} else if (timesheet) {
req.timesheet = timesheet;
next();
} else {
res.sendStatus(404);
}
});
});
timesheetsRouter.get('/', (req, res, next) => {
db.all(`select * from Timesheet where employee_id = $id`, {$id: req.params.id}, (error, rows) => {
//console.log('executed sql');
//console.log(rows);
if (!rows) {
console.log('triggered');
//console.log('this is error ' + error);
res.sendStatus(404);
//next();
} else {
console.log(rows + ' This is rows');
res.status(200).json({timesheets: rows});
}
});
});
const validateTimesheet = (req, res, next) => {
//console.log('this is menu ' + req.body);
if (!req.body.timesheet.hours || !req.body.timesheet.rate || !req.body.timesheet.date) {
return res.sendStatus(400);
}
next();
}
timesheetsRouter.post('/', validateTimesheet, (req, res, next) => {
//console.log('this is mmenu post body ' + req.body.menu.title);
db.run(`INSERT INTO Timesheet(hours, rate, date, employee_id) VALUES ($hours, $rate, $date, $employee_id)`,
{ $hours: req.body.timesheet.hours, $rate: req.body.timesheet.rate, $date: req.body.timesheet.date, $employee_id:req.params.id}, function (error) {
if (error) {
('error with sql ' + console.log(error));
return res.sendStatus(500);
}
db.get(`SELECT * FROM Timesheet WHERE id = ${this.lastID}`, (err, row) => {
if (err) {
//console.log(err);
return res.sendStatus(500);
} else {
res.status(201).json({timesheet: row});
}
});
})
})
timesheetsRouter.put('/:id', validateTimesheet, (req, res, next) => {
const timesheetToUpdate = req.body.employee;
//console.log(artistToUpdate);
//console.log("this is params " + req.params.id);
db.run(`UPDATE Timesheet SET hours=$hours, rate=$rate, date=$date where id=${req.params.id}`,
{$hours:req.body.timesheet.hours, $rate: req.body.timesheet.rate, $date:req.body.timesheet.date}), function (error, row) {
console.log(row);
if (error) {
console.log('this is error ' + error);
return res.status(404).send();
}
}
db.get(`SELECT * from Timesheet where id = $id`, {$id: req.params.id}, (error, row) => {
if(!row) {
return res.sendStatus(500);
}
//console.log(row);
res.status(200).send({timesheet: row});
})
});
module.exports = timesheetsRouter;
Run this in terminal npm install lodash --save. Lodash is a pretty nifty utility to use in any project
I have used _.isEmpty() to check whether you have received data and then proceed with it accordingly. You can check the details here https://lodash.com/docs/#isEmpty
const express = require('express');
const timesheetsRouter = express.Router({mergeParams: true});
const sqlite3 = require('sqlite3');
const _ = require('lodash');
const db = new sqlite3.Database(process.env.TEST_DATABASE || './database.sqlite');
timesheetsRouter.param('id', (req, res, next, id) => {
req.id = id;
console.log('doing name validations on ' + id);
db.get('Select * from Timesheet where employee_id = $id', {$id: id}, (error, timesheet) => {
if (error) {
next(error);
} else if (!_.isEmpty(timesheet)) {
req.timesheet = timesheet;
next();
} else {
res.sendStatus(404);
}
});
});
timesheetsRouter.get('/', (req, res, next) => {
db.all(`select * from Timesheet where employee_id = $id`, {$id: req.params.id}, (error, rows) => {
//console.log('executed sql');
//console.log(rows);
if (!rows) {
console.log('triggered');
//console.log('this is error ' + error);
res.sendStatus(404);
//next();
} else {
console.log(rows + ' This is rows');
res.status(200).json({timesheets: rows});
}
});
});
const validateTimesheet = (req, res, next) => {
//console.log('this is menu ' + req.body);
if (!req.body.timesheet.hours || !req.body.timesheet.rate || !req.body.timesheet.date) {
return res.sendStatus(400);
}
next();
}
timesheetsRouter.post('/', validateTimesheet, (req, res, next) => {
//console.log('this is mmenu post body ' + req.body.menu.title);
db.run(`INSERT INTO Timesheet(hours, rate, date, employee_id) VALUES ($hours, $rate, $date, $employee_id)`,
{ $hours: req.body.timesheet.hours, $rate: req.body.timesheet.rate, $date: req.body.timesheet.date, $employee_id:req.params.id}, function (error) {
if (error) {
('error with sql ' + console.log(error));
return res.sendStatus(500);
}
db.get(`SELECT * FROM Timesheet WHERE id = ${this.lastID}`, (err, row) => {
if (err) {
//console.log(err);
return res.sendStatus(500);
} else {
res.status(201).json({timesheet: row});
}
});
})
})
timesheetsRouter.put('/:id', validateTimesheet, (req, res, next) => {
const timesheetToUpdate = req.body.employee;
//console.log(artistToUpdate);
//console.log("this is params " + req.params.id);
db.run(`UPDATE Timesheet SET hours=$hours, rate=$rate, date=$date where id=${req.params.id}`,
{$hours:req.body.timesheet.hours, $rate: req.body.timesheet.rate, $date:req.body.timesheet.date}), function (error, row) {
console.log(row);
if (error) {
console.log('this is error ' + error);
return res.status(404).send();
}
}
db.get(`SELECT * from Timesheet where id = $id`, {$id: req.params.id}, (error, row) => {
if(!row) {
return res.sendStatus(500);
}
//console.log(row);
res.status(200).send({timesheet: row});
})
});
module.exports = timesheetsRouter;
If rows is an empty object when there is no such id, then !rows is !{} which is false. Hence it enters the else condition instead.
The negation of an empty object (!{}) is false as {} is not a falsy value. The only falsy values are false, 0, "", null, undefined, and NaN.
A simple way to check if an object is empty is Object.keys({}).length === 0. There's no need to install Lodash just to use _.isEmpty.
Simply change your code to
timesheetsRouter.get('/', (req, res, next) => {
db.all(`select * from Timesheet where employee_id = $id`, {$id: req.params.id}, (error, rows) => {
if (Object.keys(rows).length === 0) {
res.sendStatus(404);
} else {
console.log(rows + ' This is rows');
res.status(200).json({timesheets: rows});
}
});
});

getModel() is not defined - but it was defined

I am creating file upload functionality on Cloud Storage. Here's the backend code:
const Storage = require('#google-cloud/storage')
const storage = Storage({
projectId: 'a-1485'
})
const bucket = storage.bucket('a-1485.appspot.com')
function getPublicUrl (filename) {
return 'https://storage.googleapis.com/a-1485.appspot.com/${filename}'
}
function sendUploadToGCS (req, res, next) {
if (!req.file) {
return next()
}
const gcsname = Date.now() + req.file.originalname
console.log(gcsname)
const file = bucket.file(gcsname)
const stream = file.createWriteStream({
metadata: {
contentType: req.file.mimetype
}
})
stream.on('error', (err) => {
req.file.cloudStorageError = err
next(err)
})
stream.on('finish', () => {
req.file.cloudStorageObject = gcsname
req.file.cloudStoragePublicUrl = getPublicUrl(gcsname)
next()
})
stream.end(req.file.buffer);
}
module.exports = {
getPublicUrl,
sendUploadToGCS
}
In my app.js file:
app.post('/upload-image', multer.single('image'), images.sendUploadToGCS, (req, res, next) => {
let data = req.body
console.log(data)
if (req.file && req.file.cloudStoragePublicUrl) {
data.imageUrl = req.file.cloudStoragePublicUrl
}
getModel().create(data, (err, savedData) => {
if (err) {
next(err)
return
}
res.redirect(`${req.baseUrl}/${savedData.id}`);
})
}
)
However, when I upload an image I get an error thrown saying 'getModel()' is not defined. But as you can see above it is defined. What is the problem?

Categories

Resources