از آنجاکه نهایت اندازهی یک سند BSON نمیتواند بیشتر از 16 مگابایت باشد، قابلیتی به نام GridFS ایجاد شدهاست تا بتوان فایلهای باینری را در آن ذخیره کرد. GridFS شامل دو بخش مختلف برای ذخیره اطلاعات یک فایل باینری است:
- fs.chunks که برای ذخیره اطلاعات قطعههای یک فایل باینری به کار میرود.
- fs.files که برای ذخیره اطلاعات و متادیتاها به کار میرود.
قبل از هر چیزی باید بدانید که کتابخانه مربوط به GridFs در یک پکیج جداگانه عرضه شده است و باید آن از طریق nuget نصب کنیم:
install-package MongoDB.Driver.GridFS
برای آپلود یک فایل باینری به داخل سیستم از کد زیر استفاده میکنیم:
var client = new MongoClient(); var db = client.GetDatabase("publisher"); IGridFSBucket bucket = new GridFSBucket(db);
byte[] source=File.ReadAllBytes(@"D:\Untitled.png"); var options = new GridFSUploadOptions { ChunkSizeBytes = 64512, // 63KB Metadata = new BsonDocument { { "CoverType", "Front" }, { "copyrighted", true } } };
مورد دومی که مقداردهی شدهاست، متادیتاها هستند و این قابلیت را داریم که پرس و جوی خود را بر اساس آنها نیز فیلتر کنیم. این خصوصیت مقدار دریافتی از جنس BsonDocument را دریافت میکند. ولی اگر شما برای فایل خود، کلاس اختصاصی برای متادیتاها در نظر گرفتهاید میتوانید از یک Extension Method به نام ToBsonDocument استفاده کنید و شیء خود را به این نوع تبدیل کنید:
var options = new GridFSUploadOptions { ChunkSizeBytes = 64512, // 63KB Metadata = metaData.ToBsonDocument() };
در نهایت آن را آپلود میکنیم:
var id = bucket.UploadFromBytes("GoneWithTheWind", source, options);
نکته: اگر در یک کلاس، چند فیلد از جنس ObjectId دارید، مونگو در بین تشخیص شناسه اصلی سند و شناسه تصاویر، با توجه به نام خصوصیتها و غیره، تا حد زیادی هوشمند عمل میکند. ولی اگر خواستید صریحا شناسه اصلی را ذکر کنید و آن را متمایز از بقیه نشان دهید، میتوانید از خصوصیت BsonId در بالای نام فیلد ID استفاده کنید:
[BsonId] public ObjectId Id { get; set; }
جهت خواندن فایل آپلود شده، تنها کافی است از طریق شناسهی دریافتی در مرحلهی آپلود، اقدام نماییم:
var bytes = bucket.DownloadAsBytes(id);
نکته: تمام متدهای آپلود و دانلود دیتا، هم به صورت آرایه ای از بایتها و هم به صورت استریم میتوانند مورد استفاده قرار بگیرند و به ازای هر کدام، متدهای همزمان و غیرهمزمان نیز موجود هستند.
اگر قصد دارید بر اساس نام داده شده، فایل را دریافت کنید، ممکن است که چندین فایل، تحت یک نام ذخیره شده باشند که میتوانید در حالتهای مختلفی این تصاویر را واکشی نمایید:
0 : فایل اصلی
1: اولین نسخه فایل
2: دومین نسخه فایل
و الی آخر...
1-: جدیدترین نسخه فایل (مقدار پیش فرض)
2-: نسخه ماقبل جدیدترین نسخه فایل
و الی آخر...
منظور از نسخه، فایلهایی با نامی موجود و از قبل ذخیره شده هستند که نسخه جدیدی از فایل قبلی بوده و فایل اول، فایل اصلی محسوب میشود.
برای درک بهتر مسئله، من تصاویر زیر را به ترتیب از سمت راست به سمت چپ، تحت یک نام، وارد سیستم میکنم:
var client = new MongoClient(); var db = client.GetDatabase("publisher"); IGridFSBucket bucket = new GridFSBucket(db); var image=bucket.DownloadAsBytesByName("City of Glass-cover"); File.WriteAllBytes(@"D:\a.jpg",image);
برای مقداردهی خواص بالا به شکل زیر عمل میکنیم:
var client = new MongoClient(); var db = client.GetDatabase("publisher"); IGridFSBucket bucket = new GridFSBucket(db); var options = new GridFSDownloadByNameOptions { Revision = 0 }; var image=bucket.DownloadAsBytesByName("City of Glass-cover",options); File.WriteAllBytes(@"D:\a.jpg",image);
برای بازگردانی تصاویر از طریق مقادیر موجود در متادیتا، باید از کلاس ویژهای به نام GridFSFileInfo استفاده کنیم. در اینجا هم همانند روزهای اول، از کلاس بیلدر جهت ایجاد شرط استفاده میکنیم:
var client = new MongoClient(); var db = client.GetDatabase("publisher"); IGridFSBucket bucket = new GridFSBucket(db); var filter = Builders<GridFSFileInfo>.Filter.Gte(x => x.Length , 600); var sort = Builders<GridFSFileInfo>.Sort.Descending(x => x.UploadDateTime); var options =new GridFSFindOptions() { Limit = 3, Sort = sort }; var cursor = bucket.Find(filter, options); var list = cursor.ToList();
برای یافتن تصاویر بر اساس متادیتاهای تعریف شده، از کد زیر استفاده میکنیم:
var filter = Builders<GridFSFileInfo>.Filter.Eq("metadata.CoverType","Front");
تغییر نام تصاویر
جهت ویرایش یک نام فایل از طریق متدهای زیر اقدام مینماییم:
bucket.Rename(id, newFilename); //یا در حالت غیرهمزمان await bucket.RenameAsync(id, newFilename);
حذف تصویر
bucket.Delete(id); //یا await bucket.DeleteAsync(id);
برای حذف کل bucket از طریق کد زیر اقدام مینماییم:
bucket.Drop(); //یا await bucket.DropAsync();