1

I have seen many questions and solutions for this now. I am new to Mongo DB and MEAN stack development. I want to know whether there is anyway to store image content itself rather than path of the image file in Mongo DB. All the solutions suggests to store image as buffer and then use it back in the source by converting buffer to base64. I did it but the resulting output get resolves to path to the image file rather than the image content. I am looking to save image itself in DB.

// saving image
var pic = {name : "profilePicture.png",
           img : "images/default-profile-pic.png",
           contentType : "image/png"
           };

//schema
profilePic:{ name: String, img: Buffer, contentType: String }

//retrieving back
var base64 = "";
var bytes = new Uint8Array( profilePic.img.data );
var len = bytes.byteLength;
for (var i = 0; i < len; i++) {
    base64 += String.fromCharCode( bytes[ i ] );
}

var proPic = "data:image/png;base64," + base64;
console.log(proPic);

//console output
data:image/png;base64,images/default-profile-pic.png

The output for proPic resolves to "data:image/png;base64,images/default-profile-pic.png"

few links that I referred before posting this

How to do Base64 encoding in node.js?

How to convert image into base64 string using javascript

Cœur
  • 32,421
  • 21
  • 173
  • 232
Anantha
  • 89
  • 3
  • 11

2 Answers2

0

The problem is simply, that you don't read and encode the picture. Instead you use the path as a string.

Serverside using Node

If you want to perform it on the serverside with an image on the filesystem you can use something along following:

var fs = require('fs');

// read and convert the file
var bitmap = fs.readFileSync("images/default-profile-pic.png");
var encImage = new Buffer(bitmap).toString('base64');

// saving image
var pic = {name : "profilePicture.png",
           img : encImage,
           contentType : "image/png"
           };
....

Clientside

Again we need to load the image and encode it as base64. There is an answer about doing this on the client here.

using the first approach the result would be something like following:

function toDataUrl(url, callback, outputFormat){
    var img = new Image();
    img.crossOrigin = 'Anonymous';
    img.onload = function(){
        var canvas = document.createElement('CANVAS');
        var ctx = canvas.getContext('2d');
        var dataURL;
        canvas.height = this.height;
        canvas.width = this.width;
        ctx.drawImage(this, 0, 0);
        dataURL = canvas.toDataURL(outputFormat);
        callback(dataURL);
        canvas = null; 
    };
    img.src = url;
}

toDataUrl("images/default-profile-pic.png", function(encImage){
    // saving image
    var pic = {name : "profilePicture.png",
               img : encImage,
               contentType : "image/png"
               };
    //Proceed in the callback or use a method to pull out the data
    .... 
});
Community
  • 1
  • 1
Mads Buch
  • 309
  • 2
  • 10
  • Hi thanks for the reply. I figured out another way but tried this got another error for using "fs". Searched again for the solution to use "fs" on client side but got nothing. Any inputs on this would be helpful. – Anantha Apr 13 '16 at 01:40
  • Ahh, I see. I thought it was using node on the server. I have modified my answer to incorperate the client side as well. – Mads Buch Apr 13 '16 at 06:53
0

Below two links saved my time. If we use "ng-file-upload" our life becomes easy from there.

https://github.com/danialfarid/ng-file-upload#install

https://github.com/danialfarid/ng-file-upload

Below is what worked for me

//my html code

<div>
     <button type="file" ngf-select="onFileSelect($file)" ng-model="file" name="file" ngf-pattern="'image/*'" 
     ngf-accept="'image/*'" ngf-max-size="15MB" class="btn btn-danger">
     Edit Profile Picture</button>
</div>

//my js function
        function onFileSelect(file){
        //var image =  document.getElementById('uploadPic').files;
        image = file;

        if (image.type !== 'image/png' && image.type !== 'image/jpeg') {
            alert('Only PNG and JPEG are accepted.');
            return;
        }

        $scope.uploadInProgress = true;
        $scope.uploadProgress = 0;

        var reader = new window.FileReader();
        reader.readAsDataURL(image);
        reader.onloadend = function() {
            base64data = reader.result;

            $scope.profile.profilePic = base64data;

            ProfileService.updateProfile($scope.profile).then(function(response){
                $rootScope.profile = response;
                $scope.profilePicture = $rootScope.profile.profilePic;

            });

        }

    }

// when reading from the server just put the profile.profilePic value to src
src="data:image/png;base64,{base64 string}"

// profile schema
var ProfileSchema = new mongoose.Schema({
    userid:String,
    //profilePic:{ name: String, img: Buffer, contentType: String },
    profilePic:String
}

I wouldn't say this is the best solution but a good place to start.Also this limits you from uploading file size more than 16 MB in which case you can use"GridFs" in the above implementation initially the file is converted to "blob" and then I am converting it to "base64" format and adding that to my profile's string variable.

Hope this helps someone in saving their time.

Anantha
  • 89
  • 3
  • 11