mongodb-GridFS文件存储功能

GridFS


GridFS是一种在MongoDB中存储大二进制文件的机制,使用GridFS原因有以下几种:


储存巨大的文件,比如视频、高清图片等.利用GridFS可以简化需求.


GridFS会直接利用已经建立的复制或分片机制,故障恢复和扩展都很容易.


GridFS可以避免用户上传内容的文件系统出现问题.


GridFS不产生磁盘碎片


 


GridFS存储数据


GrdiFS使用两个表来存储数据:


files 包含元数据对象


chunks 包含其他一些相关信息的二进制块.


为了使多个GridFS命名为一个单一的数据库,文件和块都有一个前缀,默认情况下,前缀是fs,所以任何默认的GridFS存储将包括命名空间fs.files和fs.chunks。


各种第三方语言可以更改其前缀


 


使用GridFS mongofiles


mongofiles是从命令行操作GridFS的一种工具


四个命令:put(存储)、get(取得/下载)、list(列表)、delete(删除)




eg. ./mongofiles put testfile.zip


./mongofiles list


./mongofiles get testfile.zip


./mongofiles delete testfile.zip


验证md5 


mg5sum testfiles.zip


此时登录mongo,show tables可以看到新增2个文件fs.files和fs.chunks.


查看fs.files中的内容


db.fs.files.find();


fs.files 中存储的是一些基础的元数据信息.


db.fs.chunks.find();


fs.chunks 中存储的是一些实际的内容数据信息.


实现
GridFS是MongoDB的一个内置功能,它提供一组文件操作的API以利用MongoDB存储文件,GridFS的基本原理是将文件保存在两个Collection中,一个保存文件索引,一个保存文件内容,文件内容按一定大小分成若干块,每一块存在一个Document中,这种方法不仅提供了文件存储,还提供了对文件相关的一些附加属性(比如MD5值,文件名等等)的存储。下面是我们的部分代码:

存储文件
/// <summary>
/// 保存文件返回ID
/// </summary>
/// <param name=”tag”>Tag(用于在GridFS中显示的文件类别,如:banner,logo,test,便于清理)</param>
/// <param name=”byteFile”>byte[]</param>
/// <param name=”sourcename”>原文件名</param>
 /// <returns>返回文件编号(ObjectId)</returns>
public string GridFsSave(string tag, byte[] byteFile, string sourcename)
 {

         MongoGridFSFileInfo fileInfo;
         MongoGridFS gridFile = new MongoGridFS(“数据库名称”);
         MongoGridFSCreateOptions opt = new MongoGridFSCreateOptions();
         opt.UploadDate = DateTime.Now.ToUniversalTime();
          if (!string.IsNullOrEmpty(tag))
         {
                      BsonDocument doc = new BsonDocument();
                      doc["tag"] = tag;
                      opt.Metadata = doc;
           }//对文件进行归类

          fileInfo = new MongoGridFSFileInfo(gridFile,sourcename,opt);
          using (MongoGridFSStream gridFileStream = new MongoGridFSStream(fileInfo,System.IO.FileMode.Create))
          {
                    gridFileStream.Write(byteFile, 0, byteFile.Length);
           }

           return fileInfo.Id.ToString();//返回文件编号(ObjectId)
}

 获取文件
/// <summary>
/// 根据Id读取文件
/// </summary>
/// <param name=”sourcename”>返回原文件名</param>
/// <param name=”fileId”>文件编号(ObjectId)</param>
/// <returns></returns>
public byte[] GridFsRead(out string sourcename, string fileId)
{
          sourcename = “”;
          MongoGridFS gridFile = new MongoGridFS(“数据库名称”);
          MongoGridFSFileInfo file = gridFile.FindOneById(new ObjectId(fileId));
          sourcename = file.Name;
          MongoGridFSStream gridFileStream = file.OpenRead();
          byte[] bytes = new byte[gridFileStream.Length];
          gridFileStream.Read(bytes, 0, bytes.Length);
          return bytes;

}

 

删除文件
/// <summary>
/// 根据Id删除文件
/// </summary>
/// <param name=”fileId”>文件编号(ObjectId)</param>
public void GridFsDelete(string fileId)
{
         ObjectId oid = ObjectId.Empty;
         if (!ObjectId.TryParse(fileId,out oid))
         {
                 return;
          }
          MongoGridFS gridFile = new MongoGridFS(“数据库名称”);
          gridFile.DeleteById(oid);

}

 
由于图片文件的存取操作和展示是本项目的一个重点,因此时间和空间效率都是应该考虑进去的。结合Memcached 和GridFS的特点,我们设计了相应的策略:
[1]使用Uploadify 获取文件,由于无法判断用户的操作为有效操作,因而将图片文件放置Memcached中。当用户确定该图片文件为有效图片时,将Memcached中的图片文件,存储至GridFS中。从而避免一些垃圾数据的产生。
[2]在图片读取时,根据文件编号,从GridFS中获取图片文件。这样子保证在引用改图片文件的地方的URL地址是一致的。显示出来的图片根据页面要求,在读取的图片界面缩略或裁减。使得图片在页面展示中,不变形,不失真。
[3]可在某些场合避免重复文件。GridFS在保存一个文件时,会获取并保存文件的md5值,完全相同的文件得到的md5值是一样的,这样一来就可以手动实现全局图片唯一,在某些需要节省硬盘空间的场合可以加以利用。
[4]如果使用传统的IO文件保存方式,时间一久,文件量过大,将造成管理困难,文件的备份将变成繁琐,使用GridFS,可以让文件备份象数据库备份一样简单。

总结
通过以上方式,我们较好地解决了大量文件存取的性能、管理问题。存储在GridFS中的文件,你不用考虑文件名是否符合操作系统规范,也不用担心一个文件夹下的文件是不是太多。另外,它还有一些额外的好处: 方便保存和读取文件属性(判断文件类型、大小、像素等等);方便管理网站中大量的文件上传及管理;支持分布式应用,通过分布式MongoDB和Nginx部署,提供分布式图片的解决方案。


你可能感兴趣的:(MongoDB数据库)