Chukwuma Kingsley
Chukwuma Kingsley

Reputation: 527

Image file not being uploaded/created using multer

I am building a blog site, everything is working fine except the image upload on my Post. The post works 100% but when i attach image it does not get uploaded or created, i don't know what i am doing wrong, please i need a help. I started learning node and express few months ago. Please help me.

inside index.js file

var multer = require('multer');
var upload = multer({dest: './uploads'});

const Schema = mongoose.Schema;
const ObjectId = Schema.ObjectId;

My schema

const BlogPost = new Schema({
 author: ObjectId,
 title: String,
 body: String,
 profileimage: String,
 date: { type: Date, default: Date.now },
 comments: [{ type: Schema.Types.ObjectId, ref: 'Comment' }]
});
var Post = mongoose.model('Post', BlogPost);



router.post("/makepost", upload.single('profileimage'), (req, res) => {

 var myData = new Post(req.body);
 if(req.file) {
   console.log('Uploading File....');
   var profileimage = req.file.filename;
   console.log(profileimage)
 }else {
   console.log('No File Uploaded....');
  var profileimage = 'noimage.jpg';
 }
 myData.save()
 .then(item => {
 res.redirect('/posts');
})
.catch(err => {
 res.status(400).send("unable to save to database");
});
});

and here is my view

<form action='/makepost' method='post' enctype="multipart/form-data">
 <p>Title: <input type='text' name='title' </p>
 <p>Content: <input type='text' name='body' </p>
 <div class="form-group"> <label>Profile Image</label><input class="form-control" 
   name="profileimage" type="file" />
 <p><input type='submit' value='post'></p>

Upvotes: 1

Views: 579

Answers (1)

eol
eol

Reputation: 24555

Since you're using multer with disk-storage, you need to read the image from the temporary location before storing it with mongoose. Besides I would change the image datatype in the mongoose schema to buffer.

Something like this should work (note that I'm using async/await instead of promises directly):

router.post("/makepost", upload.single('profileimage'), async (req, res) => {

    const newPost = new Post(req.body);
    if (req.file) {         
        const imgBuffer = await fs.promises.readFile(req.file.path); // TODO add error handling
        newPost.profileimage = imgBuffer;
    }
    try {
        await myData.save();
        res.redirect('/posts');
    }catch(err) {
        res.status(400).send("unable to save to database");
    }
});

// mongoose schema
...
profileimage: Buffer,
...

You could also store the image as a Base64-encoded string and keep the datatype string in the schema.

EDIT:

As discussed in the comments - change the datatype of profileimage back to string as profileimage will just contain the path to the file.

router.post("/makepost", upload.single('profileimage'), async (req, res) => {

    const newPost = new Post(req.body);
    if (req.file) {         
        newPost.profileimage = req.file.path;
    }
    ...

Add an express middleware to serve the images, e.g.

app.use(express.static('./uploads'));

Upvotes: 1

Related Questions