i have a website where you can upload files. but i want that you can edit them too. that means the user can press edit en put a new file in and it changes the file on the database. with normal text you can do findByIdAndUpdate. but with a async function youcan. so my question is how can i do this.
here is my code for uploaden
var storage = multer.diskStorage({
destination: (req, file, cb) => {
cb(null, "uploads");
},
filename: (req, file, cb) => {
cb(null, file.fieldname + "-" + Date.now() + ".png");
},
});
var upload = multer({ storage: storage });
router.use(flash())
router.get("/create", (req, res) => {
res.render("uploadPicture", {
items: items,
user: req.auth,
title: "Upload",
});
});
router.get("/", (req, res) => {
image.find({}, (err, items) => {
if (err) {
console.log(err);
res.status(500).send("An error occurred", err);
} else {
res.render("uploadPicture", {
errMsg: req.flash('image'),
items: items,
user: req.auth,
title: "pictures",
});
}
});
});
router.post("/upload", upload.single("image"), async (req, res, next) => {
//const userid = await user.findById({_id : userid});
//console.log(userid);'
const { folder } = sanitize(req.body);
var obj = {
name: req.body.name,
userId: req.auth.userId,
folder: folder,
img: {
data: fs.readFileSync(
path.join(__dirname, "../uploads/" + req.file.filename )
),
contentType: "image/png",
},
};
image.create(obj, (err, items) => {
if (err) {
console.log("Test")
console.log(err);
req.flash('image', 'Image failed to upload!')
res.redirect("/picture")
} else {
console.log(obj);
items.save();
req.flash('image', 'Image succesfully uploaded!')
res.redirect("/picture")
}
});
});
module.exports = router;
and here is what it tried myself but didnt work because i get the error :
TypeError: Cannot read property 'findByIdAndUpdate' of undefined
router.post("/edit/:id", upload.single("image"), async(req, res ) =>{
const id = req.params.id;
console.log(req.params.id)
const { folder } = sanitize(req.body);
var obj = {
name: req.body.name,
userId: req.auth.userId,
folder: folder,
};
if(req.body.image == ""){
console.log("nothing here")
image.findByIdAndUpdate(id, {name: req.body.name,folder: folder,}, function(err, docs){
if (err) {
console.log(err);
req.flash('image', 'Image failed to upload!')
res.redirect("/picture")
} else {
console.log(obj);
req.flash('image', 'Image succesfully uploaded!')
res.redirect("/picture")
}
})
}else{
var image = {
img: {
data: fs.readFileSync(
path.join(__dirname, "../uploads/" + req.file.filename )
),
contentType: "image/png",
},
}
image.findByIdAndUpdate(id, {name: req.body.name,folder: folder,image: image}, function(err, docs){
if (err) {
console.log(err);
req.flash('image', 'Image failed to upload!')
res.redirect("/picture")
} else {
console.log(obj);
req.flash('image', 'Image succesfully uploaded!')
res.redirect("/picture")
}
})
}
})
this last part is a bit messy but i was trying some stuff
i came with a solution if anyone has to do this later
router.post("/edit/:id", upload.single("image"), async (req, res, next) => {
const id = req.params.id;
const { folder } = sanitize(req.body);
if(req.file == null){
console.log("text")
try{
const res = await image.findOneAndUpdate({_id:id}, {name: req.body.name,folder: folder})
console.log(res.name + " " + res.folder + " " + res._id);
}
catch(err){
console.log(err);
}
req.flash('imageView', 'ImageText succesfully to upload!');
res.redirect("/view/" + req.params.id);
}else{
console.log("edit picture")
try{
const res = await image.findOneAndUpdate({_id:id}, {name: req.body.name,folder: folder, img: {data: fs.readFileSync(
path.join(__dirname, "../uploads/" + req.file.filename )
),
contentType: "image/png",
}, })
console.log(res.name + " " + res.folder + " " + res._id);
}
catch(err){
req.flash('imageView', 'Image and text failed to upload!')
res.redirect("/view/" + req.params.id)
console.log(err);
}
req.flash('imageView', 'ImageText succesfully upload!');
res.redirect("/view/" + req.params.id);
}
})
this is how i did it
Related
I am using Multer to save images but I need to get the path of the image to save it to MongoDB. I am trying to get the path with req.file but it always tells me on the console that it is undefined.
this is my route:
import { Router } from 'express';
import { check, validationResult } from 'express-validator';
const multer = require('multer');
const storage = multer.diskStorage({
destination: function (req, file, cb) {
cb(null, 'uploads/products')
},
filename: function (req, file, cb) {
cb(null, new Date().toISOString().replace(/:/g, '-') + file.originalname)
}
});
const fileFilter = (req, file, cb) => {
// reject a file
if (file.mimetype === 'image/jpeg' ||file.mimetype === 'image/png') {
cb(null, true);
} else {
cb(null, false);
//cb(new Error('I don\'t have a clue!'))
}
}
const upload = multer(
{ storage: storage,
limits:{
fileSize: 1024 * 1024
},
fileFilter: fileFilter
});
let router = Router();
router.post('/', upload.single('img'),
newProduct
);
And in the new Product controller I am trying to read the req.file but the console tells me that it is undefined:
Controller:
import { Product } from '../models'
let newProduct = async (req, res = response ) => {
console.log('file ' + req.file); //UNDEFINED
try {
let { status, user, ...body } = req.body;
let productDB = await Product.findOne ( { 'name': body.name } );
if (productDB) {
return res.status(400).json({
msg:`El producto ${ productDB.name } ya existe`
})
}
let data = {
...body,
name: body.name,
user: req.user._id
}
let product = new Product( data );
await product.save();
res.status(200).json( product );
} catch (error) {
return res.status(400).json({
error
});
}
}
Console:
Thanks for your help.
you can try to do this in filename instead:
filename: function (req, file, cb) {
req.imageName = new Date().toISOString().replace(/:/g, '-') + file.originalname
cb(null, req.imageName)
}
then there:
console.log('file ' + req.file); //UNDEFINED
//you can get imageName instead
console.log('imageName',req.imageName)
//if you want url to store in database you can do this
//supposing your have images directory in root of your node server
const url = `${req.protocol}://${req.get('host')}/images/${req.body.image}`
For error handling multer suggest
const multer = require('multer')
const upload = multer().single('avatar')
app.post('/profile', function (req, res) {
upload(req, res, function (err) {
if (err instanceof multer.MulterError) {
// A Multer error occurred when uploading.
} else if (err) {
// An unknown error occurred when uploading.
}
// Everything went fine.
})
})
I wrote a custom middleware for uploading different types of file.
const { check } = require("express-validator")
const multer = require('multer')
const mime = require('mime-types')
const storage = multer.diskStorage({
destination: function (req, file, cb) {
cb(null, 'uploads/')
},
filename: function (req, file, cb) {
const filename = Date.now()+"-"+file.originalname
cb(null, filename)
}
})
const upload = multer({ storage: storage })
const uploadFile = (fieldname,filetypes,fileSize)=>{
return (req,res,next)=>{
let file = upload.single(fieldname)
file(req,res,function(err){
if (err instanceof multer.MulterError) {
req.fileError = {
param: "image",
msg: "Unable to process request"
}
return next()
} else if (filetypes.includes(mime.extension(req.file.mimetype)) === false) {
req.fileError = {
param: "image",
msg: `Only ${filetypes.toString()} allowed`
}
return next()
} else if (req.file.size > fileSize) {
req.fileError = {
param: "image",
msg: `File size should not exceed ${formatBytes(req.file.size)}`
}
return next()
}
})
}
}
course_validator = [
check("name")
.trim()
.isLength({min:3,max:100})
.withMessage("Course name should be between 3 to 100 characters")
]
app.get("/create/post",uploadFile("image",["jpeg","jpg"],122880),(req,res)=>{
const errors = validationResult(req)
if(!errors.isEmpty()){
return res.json({
status: false,
error: req.fileError ? [...errors.array(),req.fileError] : errors.array()
})
}
})
If there is no error then only I need to upload the file to uploads folder. When I upload a other than jpeg or jpg I am getting error with message that Only jpeg,jpg allowed. This is what I need. But the problem is the file is also getting uploaded to uploads folder.
For custom error messages you can go through this controller here I'm checking to file type when uploading an image and in the controller, if there is no file selected at that time I'm sending a custom message with simple if the condition after passing all if image and the products will be saved in DB
exports.postProduct = (req, res, next) => {
const title = req.body.title;
const image = req.file;
const price = req.body.price;
const description = req.body.description;
if (!image) {
return res.status(422).render("admin/add-product", {
pageTitle: "Add Product",
path: "/adminproducts",
hasError: true,
product: {
title: title,
price: price,
description: description,
},
errorMessage: "Atteched file is not an image!!!",
validationErrors: [],
});
}
const imageUrl = image.path;
const product = new Product({
title: title,
imageUrl: imageUrl,
price: price,
description: description,
userId: req.user,
});
product
.save()
.then((results) => {
console.log("Product Created Successfully");
res.redirect("/admin/products");
})
.catch((err) => {
console.log(err);
});
};
When I'm trying to upload a photo with multer and express, everything is OK. But I'm not able to send the image name in mongoose database.
The images are uploaded successfully in the upload directory. I got the imageUrl in the body, but I'm not able to update the image name in mongoose database. However the other details are updated successfully.
Check the image below:
//file upload using multer
var storage = multer.diskStorage({
destination: function (req, file, callback) {
callback(null, './uploads');
},
filename: function (req, file, callback) {
if (!file.originalname.match(/\.(jpg|png|JPEG)$/)) {
var err = new Error();
err.code = 'filetype';
return callback(err);
} else {
callback(null, Date.now() + file.originalname);
}
}
});
var upload = multer({
storage: storage,
limits: {
fileSize: 1000000
}
}).single('userImage');
app.patch('/updateProfile', authenticate, (req, res) => {
upload(req, res, function(err) {
var body = _.pick(req.body, ['name', 'email', 'mobile', 'imageUrl']);
User.findOneAndUpdate({
_id: req.user._id
}, {
$set: body
}, {
new: true
}).then((user) => {
if (!req.file) {
return res.send({
success: false,
msg: 'No file selected'
})
}
if (!user) {
res.status(404).send({
success: false,
msg: 'user not found'
})
} else {
body.imageUrl = req.file.filename;
console.log(body)
res.send({
sucess: true,
msg: 'update sucessfully',
user
})
}
}).catch((err) => {
res.send({
success: false,
msg: 'something wrong',
error: err
});
});
if (err) {
if (err.code === 'LIMIT_FILE_SIZE') {
return res.send({
success: false,
msg: 'limit file size 1MB '
})
} else if (err.code === 'filetype') {
return res.send({
success: false,
msg: 'Must be valid file extension only jpg or png'
})
} else {
return res.send({
success: false,
msg: 'something went wrong'
})
}
}
});
});
var storage = multer.diskStorage({
destination: function (req, file, callback) {
callback(null, './images/post');
},
filename: function (req, file, callback) {
if (!file.originalname.match(/\.(jpg|png|JPEG)$/)) {
var err = new Error();
err.code = 'filetype';
return callback(err);
} else {
callback(null, Date.now() + file.originalname);
}
}
});
var upload = multer({ storage: storage, limits: { fileSize: 1000000 } }).single('imageUrl');
router.post('/posts',authenticate, (req, res) => {
upload(req, res, function (err) {
if (err) {
if (err.code === 'LIMIT_FILE_SIZE') {
return res.send({ success: false, msg: 'limit file size 1MB ' })
} else if (err.code === 'filetype') {
return res.send({ success: false, msg: 'Must be valid file extension only jpg or png' })
} else {
return res.send({ success: false, msg: 'something went wrong' })
}
} else {
if (!req.file) {
return res.send({ success: false, msg: 'No file selected' })
}
var post = new Post({
heading: req.body.heading,
body: req.body.body,
imageUrl: req.file.filename,
creator:req.user.id,
});
post.save().then((result) => {
res.send({ post: result, sucess: true, msg: 'Post created' });
}).catch((err) => {
res.send({ sucess: false, msg: 'post not created', error: err })
});
}
});
});
The error prevents my webpage from being rendered. As mentioned in the title, the error lies in styles.css, when I take this file out, I do not get any errors.
styles.css is included in a separate headers.ejs file which is added in all pages, but there is only one route for which the error is shown(/cats/new). I put up some some logs around my routes and it seems when I enter /cats/new/, I am automatically redirected to a new route (get /cats/:id). I am wondering if this is the cause of the error?
I have attached my routes and the full error message below:
routes:
var express = require('express');
var router = express.Router();
var User = require('../models/user.js');
var Cat = require('../models/cat.js');
var Comment = require('../models/comment.js');
//middleware
function isAuthenticated(req,res,next) {
req.isAuthenticated() ? next() : res.redirect('/login');
}
router.get("/", function(req,res) {
res.redirect("cats");
});
router.get('/cats', function(req,res) {
Cat.find({}, function(err, cats) {
if (err) {
console.log(err);
} else {
res.render('cats', {cats: cats});
}
});
});
router.get('/cats/new', isAuthenticated, function(req,res) {
console.log('went to /cats/new');
res.render('new', {user: req.user});
});
router.post('/cats', isAuthenticated, function(req,res) {
console.log('went to post /cats');
var name = req.body.name;
var image = req.body.url;
var owner = req.user.username
var description = req.body.description;
cat = new Cat({
name: name,
image: image,
owner: owner,
description: description
});
cat.save();
User.findById(req.user._id, function(err, user) {
if (err) {
console.log(err);
} else {
user.cats.push(cat);
user.save();
}
})
res.redirect('cats');
});
router.get('/cats/:id', function(req,res) {
var id = req.params.id;
Cat.findById(id).populate('comments').exec(function(err, cat) {
if (err) {
console.log('entering get /cats/:id');
console.log(err);
} else {
console.log('no errror yet');
console.log(cat.comments);
res.render('show', {cat:cat});
}
});
});
router.post('/cats/:id', isAuthenticated, function(req,res) {
console.log(isAuthenticated);
var id = req.params.id;
Cat.findById(id, function(err, cat) {
console.log('findById running');
if (err) {
console.log(err);
console.log('err finding cat');
res.redirect('/cats');
} else {
console.log('before Comment.create');
Comment.create(req.body.comment, function(err, comment) {
console.log('after Comment.create');
if (err) {
console.log(err);
} else {
console.log('right after 2nd else');
comment.author.id = req.user._id;
console.log(req.user._id);
console.log(req.user.username);
comment.author.username = req.user.username;
comment.cat = id;
comment.save();
console.log('after saving comment');
cat.comments.push(comment);
cat.save();
console.log('saved cat');
User.findById(req.user._id, function(err, user) {
if (err) {
console.log(err);
} else {
user.comments.push(comment);
user.save();
console.log('saved user');
}
});
console.log(comment);
res.redirect("/cats/" + cat._id);
}
});
}
});
});
router.get('/cats/:id/edit', function(req,res) {
var id = req.params.id;
Cat.findById(id, function(err, cat) {
if (err) {
console.log(err);
} else {
res.render('edit.ejs', {cat:cat});
}
});
});
router.put('/cats/:id', function(req,res) {
console.log('beginning /cat/:id');
Cat.findByIdAndUpdate(
req.params.id, req.body.cat, function(err, updatedCat) {
if (err) {
console.log(err);
} else {
console.log('------------ req.body.cat');
console.log(req.body.cat);
console.log('------------ updated cat');
console.log('updated cat');
res.redirect('/cat/' + req.params.id);
console.log('not redirecting?');
}
});
router.delete('/cats/:id',isAuthenticated, function(req,res) {
var id = req.params.id;
console.log('YOU ARE TRYING TO DESTROY A CAT!');
Cat.findByIdAndRemove(id, function(err) {
if (err) {
console.log(err);
res.redirect('/user');
} else {
res.redirect('/user');
}
});
})
});
module.exports = router;
Error:
entering get /cats/:id
{ [CastError: Cast to ObjectId failed for value "styles.css" at path "_id"]
message: 'Cast to ObjectId failed for value "styles.css" at path "_id"',
name: 'CastError',
kind: 'ObjectId',
value: 'styles.css',
path: '_id',
reason: undefined }
It seems you’re including styles.css using a relative path in your template.
So when you navigate to /cats/:id, it tries to load /cats/styles.css.
In order to avoid that, you have to use an absolute path (e.g.: /styles.css or /public/styles.css – I’d recommend serving static files from a dedicated base path).
Go to
<head>
and change
<link rel="stylesheet" href="style.css">
to
<link rel="stylesheet" href="/style.css">
So I am working on an api for a todo app, and I have my 4 basic functions implemented but I'm trying to implement a search function. It worked the first time I tested it, but now every time I attempt to use it I am returning the same task no matter what my query is. Any help would be great. Also my search function is in my app.js file because I couldn't get it to function properly in my tasks.js file.
App.js
var express = require('express'),
routes = require('./routes'),
http = require('http'),
tasks = require('./routes/tasks'),
mongoose = require('mongoose'),
task = require('./routes/search');
var Task = require('./models/task').Task;
// MongoDB Connection
mongoose.connect('mongodb://localhost/task_tracker');
var app = express();
app.configure(function() {
app.set('port', 3000);
app.set('views', __dirname + '/views');
app.set('view engine', 'jade');
app.use(express.favicon());
app.use(express.logger('dev'));
app.use(express.bodyParser());
app.use(express.methodOverride());
app.use(app.router);
app.use(express.urlencoded());
app.use(express.json());
});
app.use(function(req, res, next) {
res.header("Access-Control-Allow-Origin", "*");
res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
next();
});
app.get('/', routes.index);
app.get('/tasks', tasks.index);
//app.get('/search', tasks.FindByQuery);
//app.get('/tasks/:task.:name?', task.FindByQuery);
app.get('/search', function(req, res) {
var query = req.query
//res.send(query['name']);
Task.findOne(query['name'], function(err, doc) {
if(!err && doc) {
res.json(200, doc);
} else if(err) {
res.json(500, { message: "Error loading task." + err});
} else {
res.json(404, { message: "Task not found."});
}
});
//res.end(JSON.stringify(query));
});
app.get('/tasks/:id', tasks.show);
app.post('/tasks', tasks.create);
app.put('/tasks', tasks.update);
app.del('/tasks', tasks.delete);
http.createServer(app).listen(app.get('port'), function() {
console.log("Express server listening on port 3000");
});
Tasks.js
var Task = require('../models/task').Task;
/*
* Tasks Routes
*/
exports.index = function(req, res) {
Task.find({}, function(err, docs) {
if(!err) {
res.json(200, { tasks: docs });
} else {
res.json(500, { message: err });
}
});
}
exports.show = function(req, res) {
var id = req.params.id;
Task.findById(id, function(err, doc) {
if(!err && doc) {
res.json(200, doc);
} else if(err) {
res.json(500, { message: "Error loading task." + err});
} else {
res.json(404, { message: "Task not found."});
}
});
}
exports.create = function(req, res) {
var task_name = req.body.task_name; // Name of task.
var description = req.body.task_description; // Description of the task
//Task.findOne({ name: task_name }, function(err, doc) { // This line is case sensitive.
Task.findOne({ name: { $regex: new RegExp(task_name, "i") } }, function(err, doc) { // Using RegEx - search is case insensitive
if(!err && !doc) {
var newTask = new Task();
newTask.name = task_name;
newTask.description = description;
newTask.save(function(err) {
if(!err) {
res.json(201, {message: "Task created with name: " + newTask.name });
} else {
res.json(500, {message: "Could not create task. Error: " + err});
}
});
} else if(!err) {
// User is trying to create a task with a name that already exists.
res.json(403, {message: "Task with that name already exists, please update instead of create or create a new task with a different name."});
} else {
res.json(500, { message: err});
}
});
}
exports.update = function(req, res) {
var id = req.body.id;
var task_name = req.body.task_name;
var task_description = req.body.task_description;
Task.findById(id, function(err, doc) {
if(!err && doc) {
doc.name = task_name;
doc.description = task_description;
doc.save(function(err) {
if(!err) {
res.json(200, {message: "Task updated: " + task_name});
} else {
res.json(500, {message: "Could not update task. " + err});
}
});
} else if(!err) {
res.json(404, { message: "Could not find task."});
} else {
res.json(500, { message: "Could not update task." + err});
}
});
}
exports.delete = function(req, res) {
var id = req.body.id;
Task.findById(id, function(err, doc) {
if(!err && doc) {
doc.remove();
res.json(200, { message: "Task removed."});
} else if(!err) {
res.json(404, { message: "Could not find task."});
} else {
res.json(403, {message: "Could not delete task. " + err });
}
});
}
search.js
var Task = require('../models/task').Task;
exports.FindByQuery = function(req, res) {
var query = req.query
//res.send(query['name']);
Task.findOne(query['name'], function(err, doc) {
if(!err && doc) {
res.json(200, doc);
} else if(err) {
res.json(500, { message: "Error loading task." + err});
} else {
res.json(404, { message: "Task not found."});
}
});
//res.end(JSON.stringify(query));
});
task.js
var mongoose = require('mongoose')
, Schema = mongoose.Schema;
var taskSchema = new Schema({
name : { type: String, required: true, trim: true, index: { unique: true } }
, description : { type: String, required: true }
, date_created : { type: Date, required: true, default: Date.now }
});
var task = mongoose.model('task', taskSchema);
module.exports = {
Task: task
};
I ended up figuring it out I just had to change my function a little bit. My error was in the format of my findOne function.
app.get('/search', function(req, res) {
var query = req.query
//res.send(query['name']);
Task.findOne({name: query['name']}, function(err, doc) {
if(!err && doc) {
res.json(200, doc);
} else if(err) {
res.json(500, { message: "Error loading task." + err});
} else {
res.json(404, { message: "Task not found."});
}
});
//res.end(JSON.stringify(query));
});