關於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 提供了多種語言實現的客戶端,可以根據需要進行選取,這裏使用python
的pymongo
進行操作!
下面主要是對於文件數據的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)