Reputation: 5848
How do I get a binary field from an existing mongo db document?
At the MongoDB console, if I do a find for the record of choice I get this:
{_id:ObjectId("1234"),"cover_data" : BinData(2,"ozkAAP/Y/+AAEEpGSUYAAQEBAJYAlgAA/+IFpElDQ19QUk9GSUxFAAEBAAAFlGFwcGwCIAAAbW50clJHQiBYWVogB9kAAgAZAAsAGgALYWNzcEFQUEwAAAAAYXBwbAAAAAAAAAAAAAAAAAAAAAAAAPbWAAEAAAA ..... )
In python on our web server when we do a find with pymongo it gets that field as binary and json_pickle seems to turn it to base64 automatically and alas the image looks great when sent back to the client. When I compare the generated base64 to the node.js mongo driver it's completely different and doesn't display the image properly.
Here is the code for Node.JS:
cb = function(comp) {
thumb_buffer = new Buffer(comp.thumbnail_data.value(),'binary');
comp.thumbnail_data = thumb_buffer.toString('base64');
}
In the examples and test cases here: https://github.com/christkv/node-mongodb-native I don't see any example of what I'm trying to do. There seem to be BSON deserializers and a BinaryParser that is used in the case of a whole BSON object. I tried it for just the one field and got a segmentation faults.
Running list of things I've tried:
mongo_compositions.find {_id:{$in:ids}},{},(err,compositions) ->
for comp in compositions
do(comp) =>
thumb_buffer = comp.thumbnail_data.value(true)
test_buffer = Binary(thumb_buffer)
console.log test_buffer
console.log test_buffer.toString('base64')
#thumb_buffer = BSON.deserialize thumb_buffer
#thumb_buffer.write(comp.thumbnail_data.value(true))
#comp.thumbnail_data = thumb_buffer.toString('base64')
#cover_buffer = new Buffer(comp.cover_data.value(),'binary')
#console.log thumb_buffer.toString('base64')
#console.log "#{comp.composition_author} - #{comp.thumbnail_data.length}"
#comp.cover_data = cover_buffer.toString('base64')
Upvotes: 3
Views: 9652
Reputation: 5848
As it turns out for: myDoc.binaryField.value( true );
The first 4 bytes (32-bits) are the big endian length of the size of the data. If you read from past those 4 bytes the buffer then that will end up being the data.
In my case the start of the data looked like this in hex:
63 12 00 00 ff d8 ff e0 00 10 4a 46
The python data looked like this:
ff d8 ff e0 00 10 4a 46
Binary = client.bson_serializer.Binary
binary = new Binary(myDoc.binaryField.value( true ))
buffer = new Buffer(binary.toString(),'binary')
length_buf = buffer.slice(0,4)
length = length_buf[3] << 32 | length_buf[2] << 16 | length_buf[1] << 8 | length_buf[0]
buffer.slice(4).slice(0,length).toString(enc)
Upvotes: 2
Reputation: 7935
I am a bit confused on what you are trying to do. When selecting/inserting binary elements into MongoDB using node-mongodb, you must use binary bson object.
var buffer = new Buffer(); /* your binary data */
var binary = client.bson_serializer.Binary( buffer );
var myDoc = {
binaryField: binary;
}
//And for when selecting the document
var buffer = myDoc.binaryField.value( true );
Set the toString argument to true to select it as a Buffer; false to return as "binary", but as the manual says, it should be avoided towards the buffer object.
To translate from a buffer to base64:
buffer.toString('base64');
Upvotes: 4