Mongodb Gridfs with C#, How to Store Files Such as Images

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

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.

How to save uploaded images to a MongoDB collection, and retrieve it

You should just use GridFS to do it - there is no reason why you should worry about files being too large or too small for it to make sense. GridFS was designed to store files so you should use it.

You could always store a reference to the GridFS file in a normal MongoDB document if you need to, and then load it out of GridFS when you need to use it.

See this thread: MongoDB GridFs with C#, how to store files such as images?

Storing and Retrieving image from the MongoDB (GridFs) and displaying in Html using vb.net webservice

Your code is only getting the _id from the uploaded image and not the content. What you need is the content. I found a reference already on Stack overflow, to save me some typing. The code is C# but all the classes are the same as it is the same driver.

A quick disclaimer if I may. Unless your files are huge ( > 16MB [encoded] ) and which I'm guessing they are not, GridFS may not be your best option. You will likely find more joy and less jumping through hoops if you simply encode the uploaded file as base64 and insert it as a field just as you would with any regular MongoDB document. As such you'll find this easier to deal with.

GridFS is not magic, it is essentially just a client implementation of doing exactly that prior step, but dealing with the data in smart chunks in order to overcome the 16MB limitation on a BSON document. Read more on the links:

http://docs.mongodb.org/manual/core/gridfs/

http://docs.mongodb.org/manual/faq/developers/#faq-developers-when-to-use-gridfs

That said, on with it:
So basically you want to read from the stream returned from .OpenRead() on the returned object and encode the output with base64 encoding.

As an alternate approach to in-lining the image in this way, you could pass the binary data into the response from another controller responding to images by a certain id or name. Your ajax upload then need only return the url to the image (controller end point with image id) and that would be a standard img src attribute.

It is also worthwhile to include some magic to detect the MIME type rather than hardcode that into your script.

How to retrieve and display an image which is stored in Mongodb

Here is my solution.

var fileName = @"D:CDAP\myfunction\ruwanwelimahaseya.jpg";//image which I want to save in the database
var newFileName = @"D:CDAP\myfunction\new.jpg";

        using (var fs = new FileStream(fileName, FileMode.Open))
{
var gridFsInfo = DB.GridFS.Upload(fs, fileName);
var fileId = gridFsInfo.Id;

ObjectId oid = new ObjectId(fileId.ToString());
var file = DB.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);
Image image = Image.FromStream(newFs);

f2.SizeMode = PictureBoxSizeMode.StretchImage;

f2.Image = image;

}
}
}

How to Store Images into Specified Collections in MongoDB

Note:

Database is for data

FileSystem for files

Choice Matters

Use GridFs or else use the below stuff

Instead of saving the embedded document

         "image"     : { 
"chunkSize" : 261120,
"uploadDate" : ISODate("2015-06-25T10:20:47.105Z"),
"length" : 25038,
"md5" : "b1d38a0b2ccde6da71fd6ae8fe2f637f",
"filename" : "mylogo.png"
}

Just save the reference of the image as below

{
"_id" : "USR_1",
"username" : "willsmith123",
"firstname" : "will",
"lastname" : "smith",
"status" : "ACTIVE",
"imageRef" : "unique id (objectID)"
}

Use the imageRef to get or set the image.

want to store images to gridfs from a given URL

The MongoGridFS class implements .NET's stream API so you should be able to use a MemoryStream to save the web response and insert into GridFS.

try
{
var server = MongoServer.Create("mongodb://192.168.1.8:27017/imgdb?safe=true");
var db = server.GetDatabase("imgdb");

string fileName = "logo-mongodb.png";

// Get image from URL or API
WebRequest req = WebRequest.Create("http://media.mongodb.org/" + fileName);
WebResponse response = req.GetResponse();
Console.WriteLine("Response length is " + response.ContentLength + " bytes");

// Copy from WebResponse to MemoryStream
MemoryStream memStream;
using (Stream responseStream = response.GetResponseStream())
{
memStream = new MemoryStream();

byte[] buffer = new byte[1024];
int byteCount;
do
{
byteCount = responseStream.Read(buffer, 0, buffer.Length);
memStream.Write(buffer, 0, byteCount);
} while (byteCount > 0);
responseStream.Close();
}

// Reset to beginning of stream
memStream.Seek(0, SeekOrigin.Begin);

// Save to GridFS
var gridFsInfo = db.GridFS.Upload(memStream, fileName);

// Success!
Console.WriteLine("Success!");
}
catch (Exception err)
{
Console.WriteLine("Something went wrong: "+err.Message);
}

C# MongoDB Driver with GridFS

I would store an array of DBRefs in the user's document to create a stronger association. This affords more context to the association (i.e., the target collection) in addition to just the unique ID of the image.

As for storing the ID in the image, I would skip it for a few reasons:

  • You don't want to have to constantly maintain the dual references. While this is sometimes a necessity due to the disjointed nature of document databases, the association is easy to infer from the reverse lookup.
  • Indexing the array of references in the user object will get you the user info from an image with a simple reverse-lookup. This is a trivial query and will result in negligible overhead (if any).

Having only the one-way loose association helps to future-proof your implementation should the requirements ever change to allow a single image to represent multiple users.

GridFS MongoDB retrieve metadata when downloading files

Based on https://mongodb.github.io/mongo-csharp-driver/2.10/reference/gridfs/downloadingfiles/ and https://mongodb.github.io/mongo-csharp-driver/2.10/reference/gridfs/findingfiles/#gridfsfileinfo-class:

  • Use something like https://mongodb.github.io/mongo-csharp-driver/2.10/apidocs/html/M_MongoDB_Driver_GridFS_GridFSBucket_1_OpenDownloadStream.htm to get a stream
  • Use https://mongodb.github.io/mongo-csharp-driver/2.10/apidocs/html/P_MongoDB_Driver_GridFS_GridFSDownloadStream_1_FileInfo.htm to get the file info
  • Use https://mongodb.github.io/mongo-csharp-driver/2.10/apidocs/html/P_MongoDB_Driver_GridFS_GridFSFileInfo_1_Metadata.htm to get the metadata


Related Topics



Leave a reply



Submit