Wednesday, July 3, 2013

Storing Binary Data in MongoDB

I needed to store some binary data in my MongoDB database.  I'm hosting my application on Heroku and the app has images that are closer to user data - they aren't part of the build and are added later.  Heroku has a funny file system which gets periodically cleaned.  They say data won't persist in the file system much longer than 24 hours.  As a result, I needed to keep my image data somewhere else and MongoDB seems to be a good choice.

Ruby is really good at easily reading a binary file into a Ruby string.  Ruby strings come tagged with character encoding so that magically just works.  MongoDB only uses UTF-8 encoding and will convert all strings to UTF-8 for you.  Sadly, png files don't convert automatically.

The solution to first convert the Ruby string to a BSON::Binary object.  The acronym BSON stands for "Binary JSON".  That conversion is handled in the BSON::Binary constructor.
io = File.open( fn, "rb")
mongo_binary_form = BSON::Binary.new( io.read)
io.close
You can just add/include the Binary object to your persisted object as you would any other data type.
@collection.insert( {png_data: mongo_binary_form} )
The BSON::Binary form is acceptable to use as-is in your send_data() function. The following is a snippet from a controller which returns a png image.
respond_to do |format|
  format.html do
    send_data(mongo_binary_form ,
              :filename => "your file name",
              :type=>"image/png")
  end
end

No comments:

Post a Comment