mongoDB學習筆記——存取圖片(C#)


作為一個NoSql數據庫的代表,存取多媒體數據,應該是強項吧?那么,圖片在mongoDB里是如何存取的呢?(其實,關系型數據庫存取圖片也一點問題沒有,所以我看NoSql的強項不在於是否存儲多媒體,而在於采用鍵值對的方式來存儲數據。)


mongoDB存取圖片有兩種方式:

"由於MongoDB的文檔結構為BJSON格式(BJSON全稱:Binary JSON),而BJSON格式本身就支持保存二進制格式的數據,因此可以把文件的二進制格式的數據直接保存到MongoDB的文檔結構中。但是由於一個BJSON的最大長度不能超過4M,所以限制了單個文檔中能存入的最大文件不能超過4M。為了提供對大容量文件存取的支持,samus驅動提供了“GridFS”方式來支持,“GridFS”方式文件操作需要引入新的程序集“MongoDB.GridFS.dll”。"


一、在文檔對象中存取文件

  當文件大小較小的時候,直接存入文檔對象實現起來更簡潔。比如大量圖片文件的存取等,一般圖片文件都不會超過4M。我們先實現一個上傳圖片存入數據庫,再取出來寫回頁面的例子:



using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;

using System.IO;

using MongoDB.Bson;
using MongoDB.Driver;

namespace mongotest
{
    public partial class Form3 : Form
    {
        public Form3()
        {
            InitializeComponent();
            Init();
        }
        //數據庫連接字符串
        const string strconn = "mongodb://127.0.0.1:27017";
        //數據庫名稱
        const string dbName = "test";
        MongoServer server;
        MongoDatabase db;
        void Init()
        {
            //創建數據庫鏈接
            server = MongoDB.Driver.MongoServer.Create(strconn);
            //獲得數據庫
            db = server.GetDatabase(dbName);
        }
        private void SaveImgBJSON(byte[] byteImg)
        {
            BsonDocument doc = new BsonDocument();

            doc["ID"] = 1;
            doc["Img"] = byteImg;

            MongoCollection col = db.GetCollection("thins");
            col.Save(doc);
        }
        private void btnSaveImg_Click(object sender, EventArgs e)
        {
            byte[] byteImg = File.ReadAllBytes(@"c:\temp\yl.jpg");
            SaveImgBJSON(byteImg);
        }
        private void btnShowImg_Click(object sender, EventArgs e)
        {
            MongoCollection col = db.GetCollection("thins");
            var query = new QueryDocument { { "ID", 1} };
            var result = col.FindAs<BsonDocument>(query);
            byte[] buff = (byte[])((BsonDocument)result.ToList()[0]).GetValue("Img");
            MemoryStream MS = new MemoryStream(buff);
            pictureBox1.Image = Image.FromStream(MS);
        }
    }
}

二、用GridFS方式存取文件


   在實現GridFS方式前我先講講它的原理,為什么可以存大文件。驅動首先會在當前數據庫創建兩個集合:"fs.files"和"fs.chunks"集合,前者記錄了文件名,文件創建時間,文件類型等基本信息;后者分塊存儲了文件的二進制數據(並支持加密這些二進制數據)。分塊的意思是把文件按照指定大小分割,然后存入多個文檔中。"fs.files"怎么知道它對應的文件二進制數據在哪些塊呢?那是因為在"fs.chunks"中有個"files_id"鍵,它對應"fs.files"的"_id"。"fs.chunks"還有一個鍵(int型)"n",它表明這些塊的先后順序。這兩個集合名中的"fs"也是可以通過參數自定義的。

(我想起了Sql Server的FileStream)


  如果你只是想知道怎么用,可以忽略上面這段話,下面將用法:

這里引用了兩個第三方dll,可以到https://github.com/samus/mongodb-csharp下載,編譯后得到。


using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;

using System.IO;

using MongoDB;
using MongoDB.GridFS;

namespace mongotest
{
    public partial class Form2 : Form
    {
        public Form2()
        {
            InitializeComponent();
            Init();
        }
        private void btnGridFSSave_Click(object sender, EventArgs e)
        {
            byte[] byteImg = File.ReadAllBytes(@"c:\temp\yl.jpg");
            filename = GridFsSave(byteImg);
            MessageBox.Show(filename);
        }
        private void btnGridFSShow_Click(object sender, EventArgs e)
        {
            byte[] buff = GridFsRead(filename);
            MemoryStream MS = new MemoryStream(buff);
            pictureBox1.Image = Image.FromStream(MS);
        }
        private Mongo mongo;
        private IMongoDatabase test;
        string filename;
        void Init()
        {
            var connstr = @"Server=localhost:27017";
            mongo = new Mongo(connstr);
            mongo.Connect();
            test = mongo["test"];
        }
        private string GridFsSave(byte[] byteFile)
        {
            string filename = Guid.NewGuid().ToString();

            //這里GridFile構造函數有個重載,bucket參數就是用來替換那個創建集合名中默認的"fs"的。
            GridFile gridFile = new GridFile(test);
            using (GridFileStream gridFileStream = gridFile.Create(filename))
            {
                gridFileStream.Write(byteFile, 0, byteFile.Length);
            }
            return filename;
        }
        private byte[] GridFsRead(string filename)
        {
            GridFile gridFile = new GridFile(test);
            GridFileStream gridFileStream = gridFile.OpenRead(filename);
            byte[] bytes = new byte[gridFileStream.Length];
            gridFileStream.Read(bytes, 0, bytes.Length);
            return bytes;
        }
    }
}

存儲在數據庫中如圖:



參考文章:

http://www.cnblogs.com/lipan/archive/2011/03/21/1989409.html


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM