Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Upload image then update with Multer and Express.js

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');
  }); });
like image 454
Tes3awy Avatar asked Aug 12 '18 21:08

Tes3awy


2 Answers

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
}
like image 99
onyx Avatar answered Oct 23 '22 06:10

onyx


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');
        });
});
like image 28
Ahmed Agiza Avatar answered Oct 23 '22 05:10

Ahmed Agiza