0

I'm trying to upload and store picture with Mongoose, Express and Angular. I've picked here the next solution:

.directive('fileModel', ['$parse', function ($parse) {
        return {
           restrict: 'A',
           link: function(scope, element, attrs) {
              element.bind('change', function(){
              $parse(attrs.fileModel).assign(scope,element[0].files)
                 scope.$apply();
              });
           }
        };
     }])

And the next function in controller:

$scope.uploadFile=function(){
   var fd = new FormData();
   angular.forEach($scope.files,function(file){
               fd.append('file',file);
           });

           $http.post('http://' + host + ':3000/users/' + $scope.selectedTask._id,fd,
              {
                transformRequest: angular.identity,
                headers: {'Content-Type': undefined}
              }).success(function(d){
                  console.log('yes');
              })
            }

And html:

 <input type = "file" file-model="files" multiple/>
 <button ng-click = "uploadFile()">upload me</button>
 <li ng-repeat="file in files">{{file.name}}</li>

But for some reason all I'm getting in my endpoint is an empty request object. I'm checking it with the following code in express.js:

user.route('/users/:id')
.post(function (req, res, next) {
    console.log(req.body);
})

I think the problem is that I don't know how to store something that is larger then 16MB.

halfer
  • 19,824
  • 17
  • 99
  • 186
K.Rice
  • 599
  • 1
  • 8
  • 27
  • why don't you use multer a node package which helps you store any kind of file . If you want I can show you how to use it. – sac Dahal Oct 02 '16 at 09:49
  • @sacDahal It's a first time I hear about it, I'm new with node. I'll be glad if you show me how I can upload picture. But I want to store it in mongodb because I have a userbase there and I want to store pictures together with other user's data. – K.Rice Oct 02 '16 at 09:54

1 Answers1

0

In this example you will see how to store the file you are sending in to your server directory and then pick them up from there and save them. You can also directly save them. First you pick up the file using angular, if you want you can check here for more details. Here is my small example the code is in jade.

input(type="file" name="file" onchange="angular.element(this).scope().selectFile(this.files)")
button(ng-click='savePhoto()') Save 

In your angular controller

 $scope.savePhoto = function () {
 var fd = new FormData();
  fd.append("file", $scope.files[0]);
  )) ;
$http.post("/xxx/photos", fd, {
        withCredentials: true,
        headers: { 'Content-Type': undefined },
        transformRequest: angular.identity
      }).success(function (data) {
        $scope.image = data; // If you want to render the image after successfully uploading in your db
      });
    };

Install multer using npm in your back end. And then in app.js you can set up a middleware to collect the files you are sending in. Just do console.log(req) here to check if you are getting the files till here. Multer does the magic here.

  app.use(multer({
  dest: path.join(__dirname, 'public/assets/img/profile'),
  rename: function (fieldname, filename, req, res) {
      console.log(req)// you will see your image url etc.
    if(req.session.user) return req.session.user.id;
  }
}));

So here the image will be stored in this path (public/assets/img/profile) in your server. Now you pick up the file from this server and add to your db.

var path = require('path');
  var imgPath =path.join(__dirname, '../public/assets/img/profile/' + id + '.jpg'); // this is the path to your server where multer already has stored your image
      console.log(imgPath);
      var a ;

      a = fs.readFileSync(imgPath);
      YourSchema.findByIdAndUpdate( id, {
            $set:
            {'img.data' : a,
              'img.contentType' : 'image/png' }
          }, function(err, doc) {
            if (err)console.log("oi");

          }
      );

   //In case you want to send back the stored image from the db.
      yourSchema.findById(id, function (err, doc) {
        if (err)console.log(err);

        var base64 = doc.img.data.toString('base64');
        res.send('data:'+doc.img.contentType+';base64,' + base64);

      });

In your schema store the image in type Buffer

img: { data: Buffer}
Community
  • 1
  • 1
sac Dahal
  • 1,191
  • 2
  • 13
  • 37
  • Thanks for answer. I'm trying to make it work right now, hower I have some difficulties. Since I don't have jade file I just added this: to my view. However, I'm getting error: Uncaught TypeError: angular.element(...).scope(...).selectFile is not a function – K.Rice Oct 02 '16 at 10:47
  • You can use html , you don't need jade I was to lazy to type so I copied the existing jade file. ITs just – sac Dahal Oct 02 '16 at 10:47
  • Sorry, I'm a bit dump. I'm getting this error now:(index):48 Uncaught SyntaxError: missing ) after argument list Don't know where it's from – K.Rice Oct 02 '16 at 10:53
  • fd.append("file", $scope.files[0]); )) ;// remove the )) I guess in angular controller – sac Dahal Oct 02 '16 at 10:55
  • try to console.log and see where exactly its breaking. – sac Dahal Oct 02 '16 at 11:02
  • The problem is in html, because function `savePhoto` isn't called, and browser highlights the very end of input string, – K.Rice Oct 02 '16 at 11:08
  • In your example console says `angular.element(...).scope(...).selectFile is not a function` and when i put it in my code i get this one too – K.Rice Oct 02 '16 at 11:34