天天看點

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

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

mongoDB存取圖檔有兩種方式:

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

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

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

mongoDB學習筆記——存取圖檔(C#)
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;
        }
    }
}      

存儲在資料庫中如圖: