標籤:color 簡單 async contains 集合 取圖 rmi mongodb 顯示
近期在寫一個小玩意,需要儲存一些圖片,以前我採用的是FTP或者直接資料庫儲存檔案,用FTP來儲存檔案感覺比較麻煩,用資料庫吧,還要改欄位類型,修改代碼,修改查詢語句,懶得改。
以前看過mongonDb的文章,隨就打算用Mongon來隱藏檔,然後打算百度一下看看,C#操作mongoDb的文章,全是互相抄襲,而且年代久遠,很多東西mongoDb都沒有了,隨就魔法上網。
不在介紹MongoDb是什麼,怎麼安裝,具體百度
一:使用前準備1:安裝MongoDb,百度安裝 ,並下載任意一個mongonDb的可視化軟體
我mongoDb是裝在的linux伺服器上,具體的安裝平台有讀者自己決定
可視乎軟體我推薦Robo
2:建立一個winfrom項目
右鍵項目Nuget包管理器,下載
安裝這兩個包
二:檔案上傳
這裡先用圖片來做測試
mongonDb有2種方式來儲存,1:普通的document來隱藏檔,最大為16MB,2:gridFs儲存,
1:普通document儲存範例程式碼
引用命名空間
using MongoDB.Bson;using MongoDB.Driver;
定義資料庫名和地址字
private string connStr = "mongodb://xx.93.232.xx:27017"; private string dbName = "xxxx"; private IMongoDatabase database;
獲得dataBase
var client = new MongoClient(connStr); if (client != null) { database = client.GetDatabase(dbName); bucket = new GridFSBucket(database); //這個是初始化gridFs儲存的 }
建立文檔集合
private void CheckAddCreateCollection(string collectionName) { var collectionList = database.ListCollections().ToList(); var collectionNames = new List<string>(); //獲得所有集合的名稱 collectionList.ForEach(x => { collectionNames.Add(x["name"].AsString); }); //如果沒有這個集合就建立一個 (相當於建立一個表) if (!collectionNames.Contains(collectionName)) { database.CreateCollection(collectionName); } }
寫一個關於圖片資訊的類,這裡就用帳戶圖片來表示了
public class UserAvatar { public int AvatarId { get; set; } public byte[] Avatar { get; set; } }
如果你感到疑惑為什麼要建立一個類呢,因為mongon的任何crud操作都需要一個
IMongoCollection<TDocument>
的類型來進行操作。可以理解成ef中DbSet<xxxx>
擷取前面建立好的集合
private IMongoCollection<UserAvatar> GetUserCollection(string name) { return database.GetCollection<UserAvatar>(name); //傳入集合的名字 }
讀取圖片的位元組流
var bytes = File.ReadAllBytes(@"C:\Users\哈哈哈\Desktop\test.jpg");
向mogoDb插入一條資料
private async Task< bool> AddAvater(UserAvatar avatar, IMongoCollection<UserAvatar> userAvatar) { await userAvatar.InsertOneAsync(avatar); //插入一條資料
//一下代碼是判斷了是否插入成功。 var result = userAvatar.AsQueryable().Where(x => x.AvatarId == avatar.AvatarId).Select(x => new UserAvatar { Avatar = x.Avatar, AvatarId = x.AvatarId }).ToList(); if (result.Count > 0) { this.textBox1.Text = result[0].AvatarId.ToString(); return true; } return false; }
讓我們到robo裡面看看是否插入成功了。
可以看到有資料了
從MogoDb取出一條資料
private Task<UserAvatar> GetUserAvatar(int avatarId,string collectionName) { var task = Task.Run(() => { var userAvatar = GetUserCollection(collectionName); var result = userAvatar.AsQueryable().Where(x => x.AvatarId == avatarId).Select(x => new UserAvatar { Avatar = x.Avatar, AvatarId = x.AvatarId }).ToList(); if (result.Count > 0) { return result[0]; } return null; }); return task; }
為什麼上面的代碼不在where後面直接toList呢?
答:MongoDb在文檔裡面會自動添加一個_id的欄位,這個時候反序列話,就不會成功了,報異常id不匹配。
讓我們來看下效果
顯示圖片的代碼
private void ShowImage(byte[] imageBytes) { pictureBox1.Image = null; MemoryStream memoryStream = new MemoryStream(imageBytes); Image image = Image.FromStream(memoryStream); Bitmap bitMap = new Bitmap(image, new Size(pictureBox1.Width, pictureBox1.Height)); pictureBox1.Image = bitMap; }
看看資料庫圖片ID為95的在不在。
2:grifFs隱藏檔。按照Mongodb最新的文檔來說,基本上百度到一些C#使用gridFs來隱藏檔的文章已經沒有用用了。
根據Mongon文檔的介紹,GirdF是用來儲存大於16m的檔案。
GridFS是一種儲存大於最大文檔大小(目前為16MB)的二進位資訊的方法。當您將檔案上傳到GridFS時,檔案會分成多個塊並上傳各個塊。從GridFS下載檔案時,將從塊中重新組合原始內容。
初始化
private GridFSBucket bucket; bucket = new GridFSBucket(database);
根據官方文檔說明,GridFS檔案使用兩個集合儲存在資料庫中,通常稱為“fs.files”和“fs.chunks”。上傳到GridFS的每個檔案在“fs.files”集合中都有一個文檔,其中包含有關該檔案的資訊以及“fs.chunks”集合中用於隱藏檔內容的必要數量的塊。
GridFS“bucket”是“fs.files”和“fs.chunks”集合的組合,它們共同代表可以儲存GridFS檔案的儲存桶。
GridFSBucket
對象是表示一個GridFS的桶的根對象。
可以看來使用GirdFSBucket來管理所有的檔案。
上傳檔案非常的簡單
var id = bucket.UploadFromBytes("filename", source); //source位元組數組var id = await bucket.UploadFromBytesAsync("filename", source);
如果上傳成功我們就會在robo中可以看到在collection分組下面會出現
fs.chunks,和fs.files兩個集合
先看看fs.files裡面儲存了
其中objectId,就是上面上傳代碼傳回值,toString之後的結果,
下載檔案 通過id來下載
public Task<byte[]> DownLoadFileFromGirdFs(ObjectId id) { return bucket.DownloadAsBytesAsync(id); }
如果不知道Id怎麼辦?
就要先尋找檔案了用檔案名稱,上傳時間呀也可以來尋找
我是用檔案名稱來尋找的。如果你要問用那個objectId可以不可以尋找?
可以很清楚的告訴你,我沒有實驗成功,直接就會報異常,給我報Unable to determine the serialization information(無法確定的序列化資訊)
尋找代碼
public ObjectId GetUploadFileId(string fileName) { var filter = Builders<GridFSFileInfo>.Filter.Eq(x => x.Filename, fileName); //eq方法,就是等於,還有其他的方法,具體看Mongo的api文檔 var sort = Builders<GridFSFileInfo>.Sort.Descending(x => x.UploadDateTime); //按上傳時間來倒敘一下 var options = new GridFSFindOptions { Limit = 1, Sort = sort }; using (var cursor = bucket.Find(filter,options)) { var fileInfo = cursor.ToList().FirstOrDefault(); if (fileInfo != null && fileInfo.Length > 0) { return fileInfo.Id; } return new ObjectId(); } }
現在來結合下下載與尋找代碼來看下效果
private async void button5_Click(object sender, EventArgs e) { var id = GetUploadFileId("yemobaiAvatar"); byte[] imageBytes= await DownLoadFileFromGirdFs(id); ShowImage(imageBytes); }
結果
最後附上官方文檔地址 http://mongodb.github.io/mongo-csharp-driver/
C#使用MongoDb來隱藏檔