Markus
Markus

Reputation: 1563

Saving image with mongoose

I know there are quite a few threads on this topic already, but unfortunately I didn't find my answer until now. I use angular.js with the example code from http://angular-js.in/image-upload/ to get the image from the client. This part works

Now to the node/mongodb part, here's my backend model:

var userSchema = new mongoose.Schema({
    avatar: { data: Buffer, contentType: String },
    // ...
});

module.exports = mongoose.model('User', userSchema);

and my node code:

exports.createAvatar = function (req, res) {
  var avatar = {
    data: req.body.data.image, // see below
    contentType: 'image/png'
  }

  models.DUser
    .findById(index.findUserId(req))
    .exec(function (err, user) {
      user.avatar = avatar;
      // ...
      user.save(function (err, user) {/* ... */ });

and my angularCtrl:

var foo = {
  image: image,
  imageName: image.name,
};

$http.post('/api/users', {data: foo })
    .success(function (result) { /*...*/ });

Beside from req.body.data.image I tried many different variations like req.body.data.image.dataURL, req.body.data.image.dataURL.data, but nothing worked so far. My Logging of req.body.data.image shows:

{ file: 
   { webkitRelativePath: '',
     lastModified: 1411073963000,
     lastModifiedDate: '2014-09-18T20:59:23.000Z',
     name: '3770316278.png',
     type: 'image/png',
     size: 32493 },
  url: 'blob:http%3A//127.0.0.1%3A3000/cb20debc-8a3a-468f-ab5c-39299f7ec52b',
  dataURL: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAASwAAACHCAYAAAC.....

How can I save the image to the database?

edit

I tried to save everything after base64, from req.body.data.image.dataURL into the avatar like this:

var split = req.body.data.image.dataURL.split('base64,');
var type = split[0];
var data = split[1];

var avatar = {
    data: type,
    contentType:'image/png'
};

the save message is still:

user.avatar = avatar
user.save(function (err, user) {}

But I still get the error

TypeError: Cannot set property 'avatar' of null


since my question changed a bit, I'm marking this one as solved, the new question is here: Displaying Images in Angular.js from MongoDB

Upvotes: 16

Views: 22939

Answers (4)

afshar003
afshar003

Reputation: 839

it is getting repetitive but express does not support img upload so we should do this step:

  1. first installing multer or(any thing you like) +plus fs path and sharp (npm module that resize and change the format helps for ease of job
const sharp = require("sharp");
const fs = require("fs");
const path = require("path");
const multer = require("multer");

I do suggest to read multer docs

2.we need a form for image upload

<form action="/profile" method="post" enctype="multipart/form-data">
  <input type="file" name="avatar" />
</form>



3.little set up for route

we have one file so we single method and we need tmperory destination for saving file i use a folder called upload in root of my project

let upload = multer({ dest: "upload/" });
app.post('/profile', upload.single('avatar'), function (req, res) {

  // req.file is the `avatar` file
  // req.body will hold the text fields, if there were any

const buffer = await sharp(
        path.join(__dirname, `../upload/${req.file.filename}`),
      ).png().toBuffer();
 
      const user = await User.findOneAndUpdate(
        { _id: "5ffb8e8b5f31732740314c72" },
        { avatar: buffer },
      );
})

now with find and update we successfully updated or created a avatar file

filename is a random string that the buffer named in that folder

4.go check out your database to see what happened

Upvotes: 0

mvila
mvila

Reputation: 36

It seems that your issue is not related to the image.

According to your code, the error message TypeError: Cannot set property 'avatar' of null means that the variable user is null.

And user is the result of findById(index.findUserId(req)).

So you should try to understand why this part is returning null.

Upvotes: 0

Deepak Gupta
Deepak Gupta

Reputation: 658

If you are using express than you can use express-fileupload middleware to upload files.

const fileUpload = require('express-fileupload');
app.post('/upload', fileUpload, (req, res) => {
  //Now you can use req.files.file to access the file input with name="file"
  user.avatar = {data: req.files.file.data, contentType: req.files.file.mimetype};
  //Now perform user.save
})

Upvotes: 0

Hakob Tumanyan
Hakob Tumanyan

Reputation: 26

You know, definitely it's not the best way to save image data on mongo. Instead you can save your image on any directory on your server and save only url of your file, like..

mongoose-model.js

avatar : {
    type : String
}

and on your main script you should get

let avatar_url = '/path/to/uploads/' + req.body.data.image.file.name

something like this

Upvotes: 1

Related Questions