MongoDB GridFs with C#, how to store files such as images?

C#.NetMongodbMongodb .Net-DriverGridfs

C# Problem Overview


I'm developing a web app with mongodb as my back-end. I'd like to have users upload pictures to their profiles like a linked-in profile pic. I'm using an aspx page with MVC2 and I read that GridFs library is used to store large file types as binaries. I've looked everywhere for clues as how this is done, but mongodb doesn't have any documentation for C# api or GridFs C#. I'm baffled and confused, could really use another set of brains.

Anyone one know how to actually implement a file upload controller that stores an image uploaded by a user into a mongodb collection? Thanks a million!

I've tried variations of this to no avail.

Database db = mongo.getDB("Blog");
GridFile file = new GridFile(db);
file.Create("image.jpg");
        
var images = db.GetCollection("images");
images.Insert(file.ToDocument());

C# Solutions


Solution 1 - C#

Following example show how to save file and read back from gridfs(using official mongodb driver):

 var server = MongoServer.Create("mongodb://localhost:27020");
 var database = server.GetDatabase("tesdb");

 var fileName = "D:\\Untitled.png";
 var newFileName = "D:\\new_Untitled.png";
 using (var fs = new FileStream(fileName, FileMode.Open))
 {
    var gridFsInfo = database.GridFS.Upload(fs, fileName);
    var fileId = gridFsInfo.Id;

    ObjectId oid= new ObjectId(fileId);
    var file = database.GridFS.FindOne(Query.EQ("_id", oid));

    using (var stream = file.OpenRead())
    {
       var bytes = new byte[stream.Length];
       stream.Read(bytes, 0, (int)stream.Length);
       using(var newFs = new FileStream(newFileName, FileMode.Create))
       {
         newFs.Write(bytes, 0, bytes.Length);
       } 
    }
 }

Results:

File:

File im mongodb

Chunks collection:

Chunks collection

Hope this help.

Solution 2 - C#

The answers above are soon to be outdated now that the 2.1 RC-0 driver has been released.

The way to work with files in v2.1 MongoDB with GridFS can now be done this way:

using MongoDB.Bson;
using MongoDB.Driver;
using MongoDB.Driver.GridFS;
using System.IO;
using System.Threading.Tasks;

namespace MongoGridFSTest
{
    class Program
    {
        static void Main(string[] args)
        {
            var client = new MongoClient("mongodb://localhost");
            var database = client.GetDatabase("TestDB");
            var fs = new GridFSBucket(database);
            
            var id = UploadFile(fs);

            DownloadFile(fs, id);
        }

        private static ObjectId UploadFile(GridFSBucket fs)
        {
            using (var s = File.OpenRead(@"c:\temp\test.txt"))
            {
                var t = Task.Run<ObjectId>(() => { return 
                    fs.UploadFromStreamAsync("test.txt", s);
                });

                return t.Result;
            }
        }

        private static void DownloadFile(GridFSBucket fs, ObjectId id)
        {
            //This works
            var t = fs.DownloadAsBytesByNameAsync("test.txt");
            Task.WaitAll(t);
            var bytes = t.Result;


            //This blows chunks (I think it's a driver bug, I'm using 2.1 RC-0)
            var x = fs.DownloadAsBytesAsync(id);
            Task.WaitAll(x);
        }
    }
}

This is taken from a diff on the C# driver tests here

Solution 3 - C#

This example will allow you to tie a document to an object

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using MongoDB.Driver;
using MongoDB.Driver.Linq;
using MongoDB.Bson;
using MongoDB.Driver.Builders;
using MongoDB.Driver.GridFS;
using System.IO;

namespace ConsoleApplication1
{
class Program
{
    static void Main(string[] args)
    {
        MongoServer ms = MongoServer.Create();
        string _dbName = "docs";

        MongoDatabase md = ms.GetDatabase(_dbName);
        if (!md.CollectionExists(_dbName))
        {
            md.CreateCollection(_dbName);
        }

        MongoCollection<Doc> _documents = md.GetCollection<Doc>(_dbName);
        _documents.RemoveAll();
        //add file to GridFS

        MongoGridFS gfs = new MongoGridFS(md);
        MongoGridFSFileInfo gfsi = gfs.Upload(@"c:\mongodb.rtf");
        _documents.Insert(new Doc()
        {
            DocId = gfsi.Id.AsObjectId,
            DocName = @"c:\foo.rtf"
        }
        );

        foreach (Doc item in _documents.FindAll())
        {
            ObjectId _documentid = new ObjectId(item.DocId.ToString());
            MongoGridFSFileInfo _fileInfo = md.GridFS.FindOne(Query.EQ("_id", _documentid));
            gfs.Download(item.DocName, _fileInfo);
            Console.WriteLine("Downloaded {0}", item.DocName);
            Console.WriteLine("DocName {0} dowloaded", item.DocName);
        }

        Console.ReadKey();
    }
}

class Doc
{
    public ObjectId Id { get; set; }
    public string DocName { get; set; }
    public ObjectId DocId { get; set; }
}

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionEKetView Question on Stackoverflow
Solution 1 - C#Andrew OrsichView Answer on Stackoverflow
Solution 2 - C#JoshView Answer on Stackoverflow
Solution 3 - C#John DauphineView Answer on Stackoverflow