MongoDB是文件導向的資料庫,適合用來儲存無需複雜查詢的大量資料,也可以用來儲存檔案。未超過16793600位元組(約16MB)的BSON文件能直接存在一般的集合(collection)之中,如果將檔案放進BSON文件中且沒有超過大小限制的話,則檔案可以直接存進一般的集合;如果文件會超過16793600位元組,也可以使用MongoDB提供的GridFS功能,自動將檔案切割成多個組塊(chunk)來儲存,一個組塊預設的大小為255KiB。然而,MongoDB本身並沒有判斷存入資料庫的檔案是否有重複的功能,也無法根據要存入的檔案大小來自動選擇是要存到集合裡,還是要存到GridFS中。
為了一勞永逸地解決這個問題,就必須要設計一套框架,來統一管理MongoDB內的檔案。
Mongo File Center (File Center on MongoDB)
「Mongo File Center」是筆者開發的套件,旨在建立一個易於使用且不會有冗餘的MongoDB檔案儲存空間。
Crates.io
Cargo.toml
使用方法
一個MongoDB的資料庫可以擁有一個檔案中心。一開始要先以MongoDB的主機名稱、連接埠和資料庫名稱,呼叫FileCenter
結構體的new
關聯函數,來產生出新的FileCenter
結構實體。此時順利的話,檔案中心就建立出來了。
要存放檔案進檔案中心中,可以使用FileCenter
結構實體以put_file_by_
為前綴名稱的方法,這類方法可以將檔案或是記憶體中的資料放進檔案中心,其中,以_temporarily
作為名稱後綴的方法只會將檔案保存最多一分鐘,在這期間若這檔案有被取用,就會在取用之後被刪除;而不以_temporarily
作為名稱後綴的方法,檔案在檔案中心內會永久被保存下來,同樣的檔案內容在同一資料庫中不會重複被儲存(會用SHA3-256來計算checksum,判斷檔案內容是否相同)。不管是暫時性的還是永久性的,put_file_by_
為前綴名稱的方法在檔案儲存成功時,都會回傳FileItem
結構實體,用來表示位於檔案中心內的檔案。
FileItem
結構實體的get_object_id
方法可以取得檔案在檔案中心的Object ID。FileCenter
結構實體的get_file_item_by_id
方法可以傳入一個檔案在檔案中心的Object ID,來取得FileItem
結構實體。FileCenter
結構實體的delete_file_item_by_id
方法可以傳入一個檔案在檔案中心的Object ID,來將其刪除。此外,FileCenter
結構實體還可以使用encrypt_id
和decrypt_id_token
方法來加密或是解密Object ID,加密後Object ID才可以使其安全地被分享出去。
FileItem
結構實體的into_file_data
方法可以用來取得檔案的內容,文章前面有提到,MongoDB的檔案可以存在集合或是GridFS中。因此into_file_data
方法所回傳的FileData
結構實體就會有FileData::GridFS
和FileData::FileData
這兩種變體。
以下是一個標準的使用範例:
use mongo_file_center::{FileCenter, FileData, mime};
const mongodb_uri: &str = "mongodb://localhost:27017/test_my_file_storage";
let file_center = FileCenter::new(mongodb_uri).await.unwrap();
let file_id = file_center.put_file_by_path("/path/to/file", Some("file_name"), Some(mime::IMAGE_JPEG)).await.unwrap();
let id_token = file_center.encrypt_id(file_id); // this token is safe in public
let file_id = file_center.decrypt_id_token(id_token).unwrap();
let r_file = file_center.get_file_item_by_id(file_id).await.unwrap().unwrap();
match r_file.into_file_data() {
FileData::Buffer(data) => {
// do something
}
FileData::Stream(stream) => {
// do something
}
}
預設情況下,檔案若大於256KiB,就會使用多個Document來儲存一個檔案,否則的話就會直接存在一個Document內。如果要更改這項設定,可以在建立檔案中心後使用FileCenter
結構實體的set_file_size_threshold
方法來更改,或是在尚未建立檔案中心前,使用FileCenter
結構體的new_with_file_size_threshold
關聯函數來建立檔案中心。
如果要刪除整個檔案中心,可以使用FileCenter
結構實體drop_file_center
方法。