Prashant Cholachagudda
Prashant Cholachagudda

Reputation: 13092

Read file content from MongoDB using NoRM driver

I'm trying to read the image file stored in a MongoDB, to do that I have following code in my ASP.net MVC 3 projects

public FileContentResult ProfileImage(ObjectId id)
{

    using (var db = new MongoSession<User>())
    {
        var user = db.Queryable.Where(p => p.Id == id).FirstOrDefault();
        if (user != null && user.ProfilePicture != null)
        {   
            return File(user.ProfilePicture.Content.ToArray(), user.ProfilePicture.ContentType);
        }

        return null;
    }
}

When queried the database I can see the content exist for the ProfilePicture file, but when here in the C# project the content length is 0. Is there anything wrong in the code?

Upvotes: 1

Views: 534

Answers (1)

mnemosyn
mnemosyn

Reputation: 46311

It looks as if you were embedding GridFile in User, something like

class User 
{ 
    public GridFile ProfilePicture {get; set;}
}

That won't work; at least, not through default behavior. GridFiles must be treated as first-class citizens, and they must be stored and retrieved using a GridFileCollection object:

var gridFS = conn.Database.Files();
var file = new GridFile();
// initialize file
gridFS.Save(file);
// query
var file2 = gridFS.FindOne(new { _id = file.Id });
// now, you can iterate file2.Content

You can find more working sample code in NoRM's unit tests.

The reason is that, while GridFile is basically a class like any other, the storage scheme for grid files is very different. While 'normal' objects are serialized in-place, and one document always corresponds to one object, this is not true for GridFile.

Because files can be much larger than the maximum document size in MongoDB, they'll be split up into chunks. Thus, when you store a GridFile, the driver will have to store the grid file and a number of chunks. By default, chunks are 256kB in size, so the number of chunks will depend on the data size. The default collection names are fs.files and fs.chunks.

All this logic resides in the GridFileCollection class, so it won't be executed if you're simply storing an embedded GridFile object instead of calling the Files() extension explicitly to retrieve the GridFileCollection.

Upvotes: 1

Related Questions