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?

2 Answers 2

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); 
Sign up to request clarification or add additional context in comments.

7 Comments

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
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;
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 stackoverflow.com/questions/12710001/… This is much more work
Thanks @Green, I'm displaying images with <img src="{{this.binary}}"> 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?
For small numbers, it may be OK. I have written some pros and cons here stackoverflow.com/questions/27934141/…
|
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

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.