1 GridFS簡介
當前Bson能存儲的最大尺寸是16M,我們想把大於16M的文件存入mongoDB中怎么辦呢?mongoDB提供的GridFS就是專門做這個的。使用GridFS存儲大文件時,文件被分成一個個的塊(默認大小是255 kb),將每一塊存放在一個單獨的document中。GridFS將文件存儲在兩個collection中:chunks collection和files collection,其中chunks collection保存文件塊,files collection保存文件的元數據。
2 使用mongofiles進行大文件管理
mongofiles是mongoDB內置的文件操作工具,提供了十分簡單的API讓我們可以通過命令行實現文件的上傳、下載、查找和刪除。我們使用一個視頻文件做測試。
1 上傳文件(put)
這里准備將/data/videos下的電影綠皮書(文件名:”lvpishu.mkv“)上傳到mongoDB數據庫myfiles中下,只需要使用一條命令就可以完成文件的上傳:在mongoDb的bin目錄下執行命令 mongofiles -d myfiles -l /data/videos/lvpishu.mkv put lvpishu.mkv ----host 192.168.70.131:27017 ,如果標明--host的話默認上傳到localhost。上傳完成后使用robomongo查看文件信息,如下:
使用robomongo查看上傳的文件信息,如下圖:
2 下載文件(get)
下載GridFS中的文件使用命令Get,如我們要將剛才上傳的電影,下載到/data/videos2目錄下,執行命令 mongofiles -d myfiles -l /data/videos2/lvpishu.mkv get lvpishu.mkv 即可,效果如下:
3 查找文件(list、search)
查詢 GridFS中的文件可以使用search查詢文件名包含某字符串的文件信息,使用list查詢以某字符串開頭的文件列表,因為我們只上傳了一個文件所以這里的文件列表也只展示一條文件信息,執行命令效果如下:
4 刪除文件(delete)
如果我們想刪除GridFS中的某一文件,使用delete <filename>命令
3 使用C#驅動操作GridFS
前邊我們已經使用mongoDB自帶的命令行工具mongofiles實現了大文件的增刪查操作,但是實際開發中我們更常用的方式是使用各種語言驅動來管理文件,這里展示怎么通過C#驅動來實現大文件的管理。添加GridFS的包 Install-Package MongoDB.Driver.GridFS ,C#驅動中提供了GridFSBucket(GridFS桶)對象來保存文件,它是fs.files和fs.chunks的組合,我們在使用時,最好使用GridFSBucket來和GridFS交互,盡量不要直接使用底層的fs.files和fs.chunks)。
C#驅動mongoDB的上傳和下載文件有兩種形式:①通過字節數組byte[]上傳和下載,這種方式適用於文件不大的情況,②使用stream的方式進行上傳和下載,這種形式適用於各種場合,這里就采用stream的形式做文件的上傳和下載演示,代碼如下:
class Program { static void Main(string[] args) { //連接數據庫 var client = new MongoClient("mongodb://192.168.70.133:27017, 192.168.70.131:27017, 192.168.70.129:27017"); //獲取database var mydb = client.GetDatabase("myfilesDb"); //初始化GridFSBucket var bucket = new GridFSBucket(mydb, new GridFSBucketOptions { BucketName = "lvpishu", //設置根節點名 ChunkSizeBytes = 1024 * 1024, //設置塊的大小為1M WriteConcern = WriteConcern.WMajority, //寫入確認級別為majority ReadPreference = ReadPreference.Secondary //優先從從節點讀取 }); //上傳文件 //上傳的配置項,可以添加文件元數據 var options = new GridFSUploadOptions { //ChunkSizeBytes = 1048000, Metadata = new BsonDocument { { "format", "mkv" }, { "country", "USA" } } }; //通過stream形式上傳文件 ObjectId fileId; Console.WriteLine("開始文件上傳---------------->"); string sourceFile = @"D:\迅雷下載\lvpishu.mkv"; using (var fs = new FileStream(sourceFile, FileMode.Open)) { //mongodb中的文件名為“綠皮書” Console.WriteLine("上傳中..."); fileId = bucket.UploadFromStream(filename: "綠皮書", source: fs, options: options); } Console.WriteLine("<----------------文件上傳完成"); Console.WriteLine(); //查看文件 var filter = Builders<GridFSFileInfo>.Filter; using (var cursor = bucket.Find(filter.Eq(x => x.Filename, "綠皮書"))) { var fileInfo = cursor.FirstOrDefault(); fileId = fileInfo.Id; Console.WriteLine($"文件名:{fileInfo?.Filename}, 文件大小:{fileInfo?.Length}字節, 文件上傳時間:{fileInfo?.UploadDateTime.AddHours(8)}"); Console.WriteLine($"自定義的元數據:{fileInfo?.Metadata}"); } Console.WriteLine(); //下載文件 //文件下載的位置 Console.WriteLine("開始文件下載---------------->"); string tagrgetPath = @"D:/mongoDownLoad/綠皮書下載.mkv"; using (var mongoStream = bucket.OpenDownloadStream(id: fileId)) { Console.WriteLine("下載中..."); //通過FileStream寫文件 using (FileStream fsWrite = new FileStream(tagrgetPath, FileMode.Create)) { //開辟臨時緩存內存 byte[] buffer = new byte[1024 * 1024]; while (true) { //readCount是真正讀取到的字節數 int readCount = mongoStream.Read(buffer, 0, buffer.Length); //寫入目標文件 fsWrite.Write(buffer, 0, readCount); //判斷是否讀取完成 if (readCount < buffer.Length) { break; } } } } //最好比較一下mongodb中的文件和下載文件的Md5值,如果md5相同表示下載完成 //這里為了簡單起見,就簡單判斷以下文件是否存在 if (File.Exists(@"D:/mongoDownLoad/綠皮書下載.mkv")) { Console.WriteLine("<----------------文件下載完成!"); } Console.WriteLine(); //刪除文件 bucket.Delete(id: fileId); Console.WriteLine("文件已刪除!"); Console.ReadKey(); } }
初始化GridFSBucket時可以設置一些參數:BucketName用於設置files和chunks的根節點名,如設置BucketName="lvpishu",那么在數據庫中保存文件的兩個collection的名字為lvpishu.files和lvpishu.chunks。ChunkSizeBytes用於設置數據塊的大小,這里設置數據塊大小為1M。
代碼的注釋比較詳細,這里就不多介紹了,程序運行結果如下:
小結
本節介紹了GridFS的概念,並簡單演示了怎樣使用mongofile和C#驅動進行大文件的上傳、查詢、下載、刪除操作。如果文中有錯誤的話,希望大家可以指出,我會及時修改,謝謝!