Docs Menu

Docs HomeDevelop ApplicationsMongoDB DriversRuby MongoDB Driver

GridFS

On this page

  • Creating a GridFS object ("Grid::FSBucket")
  • Working with write streams
  • Working with read streams
  • Finding file metadata
  • Deleting files
  • Working with Grid::File objects
  • Inserting Files
  • Finding Files
  • Deleting Files

The driver provides a clean and simple interface to work with storage of chunked files in the database, also known as the pattern "GridFS". The API allows you to either work with Grid::File objects or with read and write streams.

You can create a GridFS object by calling fs on a database, with optional arguments. fs returns a Grid::FSBucket object.

The options that Grid::FSBucket supports are:

Option
Description
:bucket_name
The name of the GridFS Bucket. Default is fs.
:fs_name
The name of the GridFS Bucket. Takes precedence over bucket_name. Default is fs.
:chunk_size
Specifies the size of each file chunk in the database.
:write_concern
The write concern to use when uploading files. Please see the Write Concern section under CRUD operations for how to work with write concerns.
:write
Deprecated. Same as :write_concern.
:read
The read preference to use when downloading files.

For example, you can create a GridFS bucket object with a particular read preference:

fs_bucket = database.fs( read: { mode: :secondary } )

To upload a file to GridFS using a write stream, you can either open a stream and write to it directly or write the entire contents of an IO object to GridFS all at once.

To open an upload stream and write to it:

File.open('/path/to/my-file.txt', 'r') do |file|
fs_bucket.open_upload_stream('my-file.txt') do |stream|
stream.write(file)
end
end

To upload the entire contents of an IO object in one call:

File.open('/path/to/my-file.txt', 'r') do |file|
fs_bucket.upload_from_stream('my-file.txt', file)
end

Write streams support the following options:

Option
Description
:chunk_size
Specifies the size of each file chunk in the database.
:write_concern
The write concern to use when uploading files. Please see the Write Concern section under CRUD operations for how to work with write concerns.
:write
Deprecated. Same as :write_concern.

The options can be provided as the last argument to the write stream methods:

fs_bucket.open_upload_stream('my-file.txt', write_concern: {w: 2}) do |stream|
stream.write_concern
# => #<Mongo::WriteConcern::Acknowledged:0x46980201422160 options={:w=>2}>
# ...
end
fs_bucket.upload_from_stream('my-file.txt', file, write_concern: {w: 2})

To download a file from GridFS using a read stream, you can either open a read stream and read from it directly or download the entire file all at once.

To open a download stream and read from it:

File.open('/path/to/my-output-file.txt', 'w') do |file|
fs_bucket.open_download_stream(file_id) do |stream|
file.write(stream.read)
end
end

To download the file all at once and write it to an IO object:

File.open('/path/to/my-output-file.txt', 'w') do |file|
fs_bucket.download_from_stream(file_id, file)
end

You can also download a file specified by a name and (optionally) revision number. Revision numbers are used to distinguish between files sharing the same name, ordered by date of upload. The revision number passed to open_download_stream_by_name can be positive or negative.

File.open('/path/to/my-output-file.txt', 'w') do |file|
fs_bucket.open_download_stream_by_name('my-file.txt', revision: -2) do |stream|
file.write(stream.read)
end
end

To download the entire contents of the file specified by name and (optionally) revision number:

File.open('/path/to/my-output-file.txt', 'w') do |file|
fs_bucket.download_to_stream_by_name('my-file.txt', file, revision: -2)
end

Read streams support the following options:

Option
Description
:read
The read preference to use when downloading files.

Some, but not all, of the read methods listed above pass these options to the underlying read streams. Please consult the API documentation for each method to determine whether it supports a particular option.

You can retrieve documents containing metadata about files in the GridFS files collection.

fs_bucket.find(filename: 'my-file.txt')

You can delete a file by id.

fs_bucket.delete(file_id)

This object can be used to wrap a file to be inserted into the database using GridFS and the object that is retrieved.

To create a file with raw data:

file = Mongo::Grid::File.new('I am a file', :filename => 'new-file.txt')

To create a file from a Ruby File object:

file = File.open('/path/to/my-file.txt')
grid_file = Mongo::Grid::File.new(file.read, :filename => File.basename(file.path))

To change file options such as chunk size, pass options to the constructor:

file = File.open('/path/to/my-file.txt')
grid_file = Mongo::Grid::File.new(
file.read,
:filename => File.basename(file.path),
:chunk_size => 1024
)

The following is a full list of the available options that files support.

Option
Description
:chunk_size
Sets the size of each file chunk in the database.
:content_type
Set a content type for the file.
:filename (Required)
The file name.
:upload_date
The date the file was uploaded (stored).

Files can be inserted into the database one at a time. File chunks are inserted by default into the fs.chunks collection and file metadata is inserted into the fs.files collection.

client = Mongo::Client.new([ '127.0.0.1:27017' ], :database => 'music')
file = Mongo::Grid::File.new('I am a file', :filename => 'new-file.txt')
client.database.fs.insert_one(file)

To insert into collections with a name prefix other than fs, access the filesystem with a :fs_name option.

client = Mongo::Client.new([ '127.0.0.1:27017' ], :database => 'music')
file = Mongo::Grid::File.new('I am a file', :filename => 'new-file.txt')
client.database.fs(:fs_name => 'grid').insert_one(file)

When the driver is inserting the first file into a bucket, it will attempt to create the required indexes on files and chunks collections. The required indexes are as follows:

# files collection
{ :filename => 1, :uploadDate => 1 }
# chunks collection
{ :files_id => 1, :n => 1 }, { :unique => true }

Note

If the indexes cannot be created, such as due to the current user lacking the permissions to do so, the file insert will be aborted. If the application does not have permissions to create indexes, a database administrator must create the required indexes ahead of time.

If the bucket already has files, the driver will not attempt to create indexes, even if they are missing and the current user has permissions to create them. In this case a database administrator should create the needed indexes as soon as possible to ensure data integrity.

Files can also be streamed as an alternative to a direct insert.

client.database.fs.open_upload_stream(filename) do |stream|
stream.write(file)
end

To retrieve a file from the database, call find_one with the appropriate filter.

client = Mongo::Client.new([ '127.0.0.1:27017' ], :database => 'music')
client.database.fs.find_one(:filename => 'new-file.txt') # Returns a Mongo::Grid::File

Files can also be streamed as an alternative to a direct find.

client.database.fs.open_download_stream(file_id) do |stream|
io.write(stream.read)
end
fs.download_to_stream(file_id, io)

To delete a file, pass the file object to delete_one.

client = Mongo::Client.new([ '127.0.0.1:27017' ], :database => 'music')
fs = client.database.fs
file = fs.find_one(:filename => 'new-file.txt')
fs.delete_one(file)
←  Query CacheChange Streams →