Downloading Files
There are several ways to download a file from GridFS. The two main approaches are:
- The driver downloads a file as a byte array or by writing the contents to a
Streamprovided by the application - The driver supplies a
Streamobject that the application can read the contents from
Downloading as a byte array
This is the easiest way to download a file from GridFS, assuming that the file is small enough for the entire contents to be held in memory at once.
IGridFSBucket bucket;
ObjectId id;
var bytes = bucket.DownloadAsBytes(id);
var bytes = await bucket.DownloadAsBytesAsync(id);
Downloading to a Stream
If you don’t want to hold the entire contents of the downloaded file in memory at once, you can have the driver write the contents of the file to a Stream provided by the application.
IGridFSBucket bucket;
ObjectId id;
Stream destination;
bucket.DownloadToStream(id, destination);
await bucket.DownloadToStreamAsync(id, destination);
The driver will download the contents of the GridFS file and write them to the destination Stream. The driver begins writing the contents at the current position of the Stream.
important
The driver does not close theStream when it is done. The Stream is owned by the application and it is up to the application to close the Stream when it is ready to do so.
Downloading from a Stream
In some cases the application might prefer to read the contents of the GridFS file from a Stream.
IGridFSBucket bucket;
ObjectId id;
using (var stream = bucket.OpenDownloadStream(id))
{
// read from stream until end of file is reached
stream.Close();
}
using (var stream = await bucket.OpenDownloadStreamAsync(id))
{
// read from stream until end of file is reached
await stream.CloseAsync();
}
The Stream object returned by OpenDownloadStream or OpenDownloadStreamAsync is actually a GridFSDownloadStream (a subclass of Stream), which has the following additional members in addition to those found in Stream:
public abstract class GridFSDownloadStream : Stream
{
public abstract GridFSFileInfo FileInfo { get; }
public abstract Task CloseAsync(CancellationToken cancellationToken = default(CancellationToken));
};
The FileInfo property contains information about the GridFS file being dowloaded. See the Find or FindAsync method for details about the GridFSFileInfo class.
Note
Calling CloseAsync is optional, but recommended. Since Stream is IDisposable and it is used inside a using statement, it would be closed automatically when Dispose is called. However, in async programming we want to avoid blocking and calling CloseAsync first allows the Stream to be closed with an async call. If you call CloseAsync first then Dispose will no longer block.
By default the driver assumes that you want to read the entire contents of the file from beginning to end, and returns a Stream implementation that does not support seeking, which allows for a more efficient implementation.
If you do want to use Seek with the returned Stream, you can use the options parameter to indicate that.
IGridFSBucket bucket;
ObjectId id;
var options = new GridFSDownloadOptions
{
Seekable = true
};
using (var stream = bucket.OpenDownloadStream(id, options))
{
// this time the Stream returned supports seeking
stream.Close();
}
using (var stream = await bucket.OpenDownloadStreamAsync(id, options))
{
// this time the Stream returned supports seeking
await stream.CloseAsync();
}
Downloading by filename
All the previous examples used an Id to specify which GridFS file to download. You can also use a filename to specify which GridFS file to download, but in this case you might need to indicate which “revision” of the file you want to download if there are multiple GridFS files with the same filename.
Revisions are identified using an integer, as follows:
- 0 = the original version uploaded
- 1 = the first revision of the file
- 2 = the second revision of the file
- …
- -2 the second newest revision of the file
- -1 the newest revision of the file
The default value for the revision is -1 (i.e. the newest revision).
The following examples all download the newest revision:
IGridFSBucket bucket;
string filename;
var bytes = bucket.DownloadAsBytesByName(filename);
// or
Stream destination;
bucket.DownloadToStreamByName(filename, destination);
// or
using (var stream = bucket.OpenDownloadStreamByName(filename))
{
// read from stream until end of file is reached
stream.Close();
}
var bytes = await bucket.DownloadAsBytesByNameAsync(filename);
// or
Stream destination;
await bucket.DownloadToStreamByNameAsync(filename, destination);
// or
using (var stream = await bucket.OpenDownloadStreamByNameAsync(filename))
{
// read from stream until end of file is reached
await stream.CloseAsync();
}
If you want to download a different revision, you specify the desired revision using the options parameter.
IGridFSBucket bucket;
string filename;
var options = new GridFSDownloadByNameOptions
{
Revision = 0
};
var bytes = bucket.DownloadAsBytesByName(filename, options);
// or
Stream destination;
bucket.DownloadToStreamByName(filename, destination, options);
// or
using (var stream = bucket.OpenDownloadStreamByName(filename, options))
{
// read from stream until end of file is reached
stream.Close();
}
var bytes = await bucket.DownloadAsBytesByNameAsync(filename, options);
// or
Stream destination;
await bucket.DownloadToStreamByNameAsync(filename, destination, options);
// or
using (var stream = await bucket.OpenDownloadStreamByNameAsync(filename, options))
{
// read from stream until end of file is reached
await stream.CloseAsync();
}