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:
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 DBRef
s 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
Double Precision Problems on .Net
How Much Faster Is C++ Than C#
Simple Animation Using C#/Windows Forms
Difference Between Char.Isdigit() and Char.Isnumber() in C#
How to Pass a Username/Password in the Header to a Soap Wcf Service
How to Programmatically Change Active Directory Password
Complex Type Is Getting Null in a APIcontroller Parameter
How to Best Implement Equals for Custom Types
.Net Framework 3.5 and Tls 1.2
How to Show the Sum of in a Datagridview Column
How to Detect a Process Start & End Using C# in Windows
Why Is Typedreference Behind the Scenes? It's So Fast and Safe... Almost Magical!
How to Get the Directory from a File's Full Path
Convert File Path to a File Uri
Checking If a String Array Contains a Value, and If So, Getting Its Position