So I have completed the stage of uploading an image with Multer and Express.js from here. Now if I edit an article having that image, I get the correct image. But, what I want to do is that if the image is still the same, don't do anything, else take the new uploaded image.
My problem is that input[type="file"]
doesn't accept attr value
to be set by hand. I also read this question but I don't know if it's relevant to my question or not!
What I get when I submit the edits is Cannot read property 'filename' of undefined
. Yet, I get all other form fields correctly from the request.
I am using Mongoose and methodOverride for PUT and DELETE requests.
Multer
const multer = require('multer');
const storage = multer.diskStorage({
destination: (_req, _file, done) => {
done(null, path.join(__dirname, './../../public/uploads/'));
},
filename: (_req, file, done) => {
done(
null,
`${file.fieldname}-${Date.now()}${path.extname(file.originalname)}`,
);
},
});
const upload = multer({
storage
});
For POST request
router.post('/add', authenticate, upload.single('image'), (req, res) => {
const userId = req.user.id;
const body = req.body;
const title = body.title;
const content = body.content;
const featured = body.featured;
const image = req.file.filename;
const newPost = new Post({
title,
content,
image,
userId,
featured
});
newPost
.save()
.then(post => {
if (!post) {
return req.flash('error', 'Unable to add article!!!');
}
req.flash('success', 'Added article successfully');
})
.catch(err => {
return req.flash('error', 'Unable to add article!!!');
});
res.redirect('/posts');
},
);
For PUT request
router.put(/post/edit/:id', authenticate, upload.single('image'), (req, res) => {
const id = req.params.id;
const body = req.body;
console.log('body:', body);
console.log('req:', req);
const title = body.title;
const content = body.content;
const featured = body.featured;
const image = req.file.filename;
Post.findOneAndUpdate(id,
{
$set: {
title,
content,
featured,
image
}
},
{ new: true }
).then(post => {
req.flash('success', 'Edits submitted successfully');
res.redirect('/posts');
})
.catch(err => {
return req.flash('error', 'Unable to edit article');
}); });
From the documentation of multer.single(fieldname)
Accept a single file with the name fieldname. The single file will be stored in req.file.
Because you are doing upload.single('image')
your multer
will accept file with the name
image and store it to req.file.image
. You are however referring it with filename. You should therefore replace req.file.filename
with req.file.image
.
Also when uploading a new file or editing you would want to check if the file
exists before processing it with multer
to avoid property of undefined error.
if (req.file) {
// your code
}
You simply need to check if there is a file attached to the request using if (req.file)
and modify the database query accordingly.
So your post edit code can go like this:
router.put('/post/edit/:id', authenticate, upload.single('image'), (req, res) => {
const id = req.params.id;
const body = req.body;
console.log('body:', body);
console.log('req:', req);
const title = body.title;
const content = body.content;
const featured = body.featured;
const updates = {
title,
content,
featured
};
if (req.file) {
const image = req.file.filename;
updates.image = image;
}
Post.findOneAndUpdate(id, {
$set: updates
}, {
new: true
}).then(post => {
req.flash('success', 'Edits submitted successfully');
res.redirect('/posts');
})
.catch(err => {
return req.flash('error', 'Unable to edit article');
});
});
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With