16

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

Towkir
  • 3,889
  • 2
  • 22
  • 41
Markus
  • 1,565
  • 6
  • 26
  • 57
  • so you want to store the Blob data into mongo, or just the path of the image on server? – Ravi Dec 08 '14 at 08:00
  • I want to store the blob into mongo – Markus Dec 08 '14 at 08:06
  • hmmm, the file data might be in your `req.files` object. And refer [`GridFS`](http://www.mongodb.org/display/DOCS/GridFS) for storing binary data in mongo. – Ravi Dec 08 '14 at 08:24
  • req.files is undefined. I looked at the GridFS doku, but I'm still not sure how I can save binary data into my mongodb – Markus Dec 08 '14 at 08:41
  • 1
    Looks like the dataURL field has the image data encoded in base64. If you want to store the image data, just store what is after `data:image/png;base64,`, it's a base64 encoded png. – tomaoq Dec 08 '14 at 08:56
  • I tried that that (edited my original post), but it still doesn't work. But what I dont get is - whats the correct way to do this with mongodb/node? Unfortunately I haven't found a working `gridFS` example either – Markus Dec 08 '14 at 09:08
  • 2
    In your `EDIT`, the user object is `null`. As mentioned in the error. – Ravi Dec 08 '14 at 09:17
  • thank you, that was a dumb mistake on my part.. I'm still a little bit confused though how storing images in mongodb with node.js is supposed to work now. Splitting the `dataURL` in substrings doesn't sound like the right thing to do for me. – Markus Dec 08 '14 at 19:46
  • @Markus I have been trying to figure out how to save images in mongoDB using mongoose and then display them on the front end but Ive been stuck for days. Any chance you could be able to help? I am not even sure whether I saved the images correctly in mongoDB. Heres my question on SO any help will be greatly appreciated http://stackoverflow.com/questions/34904157/reading-and-displaying-images-from-mongodb-using-gridfs – Skywalker Jan 21 '16 at 10:42
  • "since my question changed a bit, I'm marking this one as solved, the new question is here": https://stackoverflow.com/questions/27367611/displaying-images-in-angular-js-from-mongodb – wp78de Apr 11 '18 at 02:10
  • For storing image in mongodb multer is used would you like to use multer? If yes then i can show example. – Savan Padaliya Feb 15 '20 at 09:43
  • You can try this one ```var buffer = fs.readFileSync(filePath or URL,{ encoding: 'base-64' });``` ```user.avatar = buffer``` ```user.save()``` – Ashish Choubey Jun 13 '20 at 04:33
  • Storing image on Mongodb is not a good idea. as you will get max 4 MB or so space for single record. However Mongodb 5.0 have GridFS. you can check that out https://docs.mongodb.com/manual/core/gridfs/ – Dipten Sep 22 '21 at 05:10

4 Answers4

1

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

0

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
})
Deepak Gupta
  • 614
  • 1
  • 7
  • 14
0

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.

mvila
  • 36
  • 3
0

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

afshar003
  • 765
  • 6
  • 6