1

How would I upload an image binary directly to the db? I read that GridFS is only needed for larger files.

My input:

<template name="pixUpload">
    <input type="file" name="myFile" class="myPixInput">
</template>

And the template:

Template.pixUpload.events({
    'change .myPixInput': function(event, template) {
        event.preventDefault();
        var pixBinaryVar = event.target.myFile.value;
        MyPix.insert({
            binary: pixBinaryVar;
        })
    }
})

It doesn't work and I get an error that the value is not defined. Why?

Kai
  • 417
  • 4
  • 15

2 Answers2

5
Template.pixUpload.events({
    'change .myPixInput': function(event, template) {
        event.preventDefault();
        var file = event.target.files[0]; //assuming you have only 1 file
        var reader = new FileReader(); //create a reader according to HTML5 File API

        reader.onload = function(event){
          var result = reader.result //assign the result, if you console.log(result), you get {}
          var buffer = new Uint8Array(result) // convert to binary
          MyPix.insert({binary: buffer});
        }

        reader.readAsArrayBuffer(file); //read the file as arraybuffer
        //reader.readAsDataURL(file)

    }
})

As of Meteor 1.0, when you send binary/buffer inside Meteor.call or collection.insert, it get converted to EJSON from the client, then when it reaches the server, it get converted back to the original binary/buffer

If you open the chrome console and look at the websocket traffic, you see the EJSON binary string, which is base64 encoded. So the alternative way is to use reader.readAsDataURL, this converts your image directly to base64, saving Meteor from doing this again.

reader.onload = function(event){
  MyPix.insert({binary: reader.result});
}
reader.readAsDataURL(file);
Green
  • 4,950
  • 3
  • 27
  • 34
  • Thanks a LOT @Green! – your code works and I'm starting to understand what is happening here. If I'm correct you recommend the second approach by using `reader.readAsDataURL`. Also, can I ask you how you would display a `[object Uint8Array]` in the browser? I could not work that out. In general, is this a good approach for a small-images database? Most of our files are low resolution: [eBoy](http://hello.eboy.com/eboy/category/everything/explore/parts/) – Kai Jan 14 '15 at 11:29
  • If you call readAsDataUrl, console.log the result will give you "data:image/jpg;base64,xxx...". You can then do this: var img = document.getElementbyId('someImgId'); img.src = result; Or after saving into the collection, if you store the binary as base64 Assuming you called MyPix.insert({name:'somePic',binary:result}); Then to show the image, you call var result = MyPix.findOne({name:'somePic'}).binary then assign img.src = result; – Green Jan 14 '15 at 11:57
  • On the other hand, if you call readAsArrayBuffer() then convert to Uint8Array. When you try to console.log the array, you get [.....] To display as it as picture, you need to do var result = MyPix.findOne({name:'somePic'}).binary then convert this result into base64: var result_b = arrayToBase(result) then assign img.src = result_b see http://stackoverflow.com/questions/12710001/how-to-convert-uint8-array-to-base64-encoded-string This is much more work – Green Jan 14 '15 at 11:58
  • Thanks @Green, I'm displaying images with `` for now. Not sure I understand the getElementById approach – but I'm new to JS – I have to do some homework I guess. Anyway, I'm curious what you think about using this concept for a small-image database – or should I go for CollectionFS in any case? – Kai Jan 15 '15 at 10:48
  • For small numbers, it may be OK. I have written some pros and cons here http://stackoverflow.com/questions/27934141/meteor-uploading-file-from-client-to-mongo-collection-vs-file-system-vs-gridfs/27934142#27934142 – Green Jan 15 '15 at 13:45
  • Wow, this is very useful @Green. Can't yet comment on other threads though – so I'll have to do it here. First question is if the quantity of images is an issue. Say we have 20,000 images – is that a problem with DDP? Second question would be if it is possible to use ImageMagick to resize and modify images. If I understand correctly, it's not (at the moment). – Kai Jan 16 '15 at 10:20
  • This is about scaling, if you publish a lot of images through Meteor.publish, this will consume a lot of memory... http://stackoverflow.com/questions/13113256/how-efficient-can-meteor-be-while-sharing-a-huge-collection-among-many-clients/21835534#21835534 I am not familiar with ImageMagick, but I suppose you can transform the image stream to modify it – Green Jan 16 '15 at 11:09
0

One option for small images, you can have is change the image to base64 and store it in database.

This can be done with creating html canvas and draw image within it and get base64 image-

Here is reference for same -

How to convert an image to base64 in JavaScript

Community
  • 1
  • 1
ajduke
  • 4,991
  • 7
  • 36
  • 56