关于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)