Rack:GridFS is a Rack middleware for creating HTTP endpoints for files stored in MongoDB’s GridFS. You can configure a prefix string which will be used to match the path of a request, and further look up GridFS files based on either their ObjectId
or filename
field.
For example,
GET '/gridfs/someobjectid'
If the prefix is “gridfs”, then the id will be be “someobjectid”.
This version is currently based on mongo-1.1+. As there were significant changes to the GridFS API prior to v1.0, you may have luck with the git-tagged version 0.2.0 of this library with earlier versions of the driver.
gem install rack-gridfs
require 'rack/gridfs' use Rack::GridFS, :prefix => 'gridfs', :hostname => 'localhost', :port => 27017, :database => 'test'
Options:
-
prefix
: a string used to match against incoming paths and route to through the middleware. Default ‘gridfs’. -
lookup
: whether to look up a file based on:id
or:path
(example below). Default is:id
.
You must also specify MongoDB database details:
-
hostname
: the hostname/IP where the MongoDB server is running. Default ‘localhost’. -
port
: the port of the MongoDB server. Default 27017. -
database
: the name of the MongoDB database to connect to. -
username
andpassword
: if you need to authenticate to MongoDB.
require 'rubygems' require 'sinatra' require 'rack/gridfs' use Rack::GridFS, :database => 'test', :prefix => 'gridfs' get /.*/ do "The URL did not match a file in GridFS." end
To use Rack::GridFS
in a Rails application, add it as middleware in application.rb
or config/environments/*
with something like this:
config.middleware.insert_after Rack::Runtime, Rack::GridFS, :prefix => 'uploads', :database => "my_app_#{Rails.env}"
Run rake middleware
to decide for yourself where to best place it in the middleware stack for your app using the Rails convenience methods, taking into consideration that it can probably be near the top since it simply returns a “static” file or a 404.
The :lookup => :path
option causes files to be looked up from the GridFS store based on their filename
field (which can be a full file path) rather than ObjectId
(requests still need to match the prefix
you’ve set). This allows you to find files based on essentially arbitrary URLs such as:
GET '/prefix/media/images/jane_avatar.jpg'
How filenames are set is specific to your application. We’ll look at an example with Carrierwave below.
NOTE: The Mongo Ruby driver will try to create an index on the filename
field for you automatically, but if you are using filename lookup you’ll want to double-check that it is created appropriately (on slaves only if you have a master-slave architecture, etc.).
Path lookup works well for usage with Carrierwave. As a minimal example with Mongoid:
# config/initializers/carrierwave.rb CarrierWave.configure do |config| config.storage = :grid_fs config.grid_fs_connection = Mongoid.database config.grid_fs_access_url = "/uploads" end # app/uploaders/avatar_uploader.rb class AvatarUploader < CarrierWave::Uploader::Base # (Virtual) path where uploaded files will be stored, appended to the # gridfs_access_url by methods used with view helpers def store_dir "#{model.class.to_s.underscore}/#{mounted_as}/#{model.id}" end end # app/models/user.rb class User include Mongoid::Document mount_uploader :avatar, AvatarUploader end # app/views/user/show.html.erb <%= image_tag(@user.avatar.url) if @user.avatar? %>
This will result in URL paths like /uploads/user/avatar/4d250d04a8f41c0a31000006/original_filename.jpg
being generated for the view helpers, and Carrierwave will store user/avatar/4d250d04a8f41c0a31000006/original_filename.jpg
as the filename
in GridFS. Thus, you can configure Rack::GridFS
to serve these files as such:
config.middleware.insert_after Rack::Runtime, Rack::GridFS, :prefix => 'uploads', :lookup => :path, :database => "my_app_#{Rails.env}"
Copyright © 2010 Blake Carlson. See LICENSE for details.