關於mongodb中的GridFS的使用

關於mongodb中的GridFS的基本使用

基本的說明

mongo 作爲一個非關係型數據庫,使用非常方便,在項目中也經常的使用。
這裏主要是說一些他的 網格文件系統 的使用。

在我們想要存儲一些文件的時候,可以存放得到文件系統裏面,然後使用的時候通過程序讀取。
當然還可以使用數據庫進行存放一些小的文件,這裏使用mongo的GridFS。

GridFS 裏面存放的主要是有兩個集合,一個集合存放數據的基本信息,另外一個集合主要是存放文件的數據信息,並且這些數據據信息被分成了塊。相同的文件即使改了文件名,在儲存的時候,文件數據也不會被重複存儲,提高了磁盤的使用率。如下,文件信息和文件數據的存儲結構如下:

文件信息數據:

{
    "_id" : ObjectId("5d15e79d13f3c103886f003f"),
    "chunkSize" : 261120,
    "file_name" : "dev.tgz",
    "filename" : "dev.tgz",
    "length" : 27569699,
    "uploadDate" : ISODate("2019-06-28T10:10:38.348Z"),
    "md5" : "9b1aa63c1cf49dccdd20b962fe313989"
}

解釋:其中_id 表示文檔ID也是對應的文件ID ,chunkSize 表示塊的大小,上傳日期,md5 等 也都很好理解

文件塊數據:

{
    "_id" : ObjectId("5d15dd8a13f3c133d4b65d76"),
    "n" : 0,
    "data" : {
        "$binary" : "H4sIACkT/lgAA+T9y5Ic15YlCOa4v0ILIuwgRcxx/YkHIyt...好多二進制...dnJBcmQoHFrlqbwhHn/O", 
        "$type" : "00" 
    },
    "files_id" : ObjectId("5d15dd8a13f3c133d4b65d75")
}

解釋:這裏的_id 表示的是文檔ID files_id 表示的是文件ID 也就是將文件塊關聯起來的ID, n標明序號,指明瞭塊的順序。其中data裏面是數據,binary 裏面是二進制數據 type 表示的是類型。

使用

在使用的時候,mongo 提供了多種語言實現的客戶端,可以根據需要進行選取,這裏使用pythonpymongo進行操作!

下面主要是對於文件數據的CRUD操作:

代碼裏主要包括了添加文件,獲取文件信息,獲取文件id,迭代文件數據,刪除和查看文件等操作,使用簡單,可以直接拷貝使用

需要修改的就是可能項目中需要根據配置文件設置客戶端,也就是create_db稍微修改一下就可以。另外需要注意的是query是在添加和查詢的時候使用。可以自定義一些參數信息。測試的話可以直接修改一下主機和端口就行。


from pymongo import MongoClient
from gridfs import GridFS


class GFS(object):
    """GridFS的操作的工具類"""
    
    def __init__(self, file_db_name, file_table_name):
        """這裏兩個參數分別是文件數據庫名稱,和表名稱"""
        file_db, file_table = self.create_db(file_db_name, file_table_name)
        self.file_db = file_db
        self.file_table = file_table
        # 注意下面是file_table_name
        self.fs = GridFS(file_db, file_table_name)

    @staticmethod
    def create_db(file_db_name, file_table_name):  # 連接數據庫,並創建文件數據庫與數據表
        client = MongoClient('localhost', 27017)
        # client = mrc.router("%s.%s" % (file_db_name, file_table_name))
        db = client[file_db_name]
        file_table = db[file_table_name]
        return db, file_table

    def save(self, file_data, query):
        is_existed = self.fs.exists(query)
        if is_existed:
            return self._get_file_id(query)
        else:
            new_obj_id = self.fs.put(file_data, **query)
            return new_obj_id

    def get_file(self, query):
        file_id = self._get_file_id(query)
        if not file_id:
            return False
        gf = self.fs.get(file_id)
        file_meta = {
            "md5": gf.md5,
            "file_name": gf.filename,
            "length": gf.length,
            "content_type": gf.content_type,
            "upload_date": gf.upload_date,
            "chunk_size": gf.chunk_size,
            "f_id": file_id
        }
        return file_meta

    def iter_file(self, file_id):
        gf = self.fs.get(file_id)
        chunk_data = gf.readchunk()
        while chunk_data:
            yield chunk_data
            chunk_data = gf.readchunk()

    def _get_file_id(self, query):
        obj = self.fs.find_one(query)
        if obj:
            return obj._id
        return False

    def delete_file(self, file_id):
        res = self.fs.delete(file_id)
        print res

    def list(self):
        print self.fs.list()


def insert_file(gfs, file_path, query):
    with open(file_path, "rb") as f:
        f_data = f.read()
        print gfs.save(f_data, query)


if __name__ == '__main__':
    gfs = GFS('excel_file', 'excel_table')
    file_path = 'E:/datas/dev1.tgz'
    query = {'file_name': 'dev1.tgz', 'filename': 'dev1.tgz'}

    insert_file(gfs, file_path, query)

    f_id = gfs.get_file(query)["f_id"]

    with open("tt.tgz", "wb") as f:
        for chunk in gfs.iter_file(f_id):
            f.write(chunk)

    gfs.list()

    # gfs.delete_file(f_id)

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章