.NET MongoDB Driver GridFS 2.2原理及使用示例

一、API解读

1 GridFSBucketOptions

1)public string BucketName { get; set; }

获取或设置bucket名称

2)public int ChunkSizeBytes { get; set; }

获取或设置块的字节大小

3)public ReadConcern ReadConcern { get; set; }

获取或设置读关注

4)public ReadPreference ReadPreference { get; set; }

获取或设置读优先权

1)public WriteConcern WriteConcern { get; set; }

获取或设置写关注

2 GridFSUploadOptions:GridFS上传操作选项

1)[Obsolete("Place aliases inside metadata instead.")]

        public IEnumerable<string> Aliases { get; set; }

(已不再使用)获取或设置别名

2)public int? BatchSize { get; set; }

获取或设置一堆的大小

1) public int? ChunkSizeBytes { get; set; }

获取或设置块的字节大小

4)[Obsolete("Place contentType inside metadata instead.")]

        public string ContentType { get; set; }

(已不再使用)获取或设置资源类型

5)public BsonDocument Metadata { get; set; }

获取或设置元数据

3 GridFSDownloadOptions:下载操作选项

1)public bool? CheckMD5 { get; set; }

获取或设置是否检验MD5值

2)public bool? Seekable { get; set; }

获取或设置返回流是否支持查找

4 GridFSFindOptions:查找选项

public SortDefinition<GridFSFileInfo> Sort { get; set; }

获取或设置排序

5 GridFSFileInfo

存储在数据库中的一个GridFS文件的信息

1)public BsonDocument BackingDocument { get; }

获得支持文件

2)public int ChunkSizeBytes { get; }

获得块大小

3)public string Filename { get; }

获得文件名

4)public ObjectId Id { get; }

获得标识

5)public long Length { get; }

获得文件长度

6)public string MD5 { get; }

获得MD5值

7)public BsonDocument Metadata { get; }

获得元数据

8)public DateTime UploadDateTime { get; }

获得上传时间

6 GridFSBucket

说明:

  1. 下述操作中的参数列表中,id为files_id的值,而不是_id的值
  2. 有的操作有相应的异步方法,这里没有列出
  3. 当多个文件的文件名相同时,可以通过指定版本来选择下载哪一个文件,默认的是-1(最新上传的版本),0表示原始版,1表示第一个版本,2...依次类推;-1表示最新版本,-2表示次新版本,-3...依次类推

1)public GridFSBucket(IMongoDatabase database, GridFSBucketOptions options = null);

构造函数

参数:

database:待操作数据库

options :构造GridFS实例的选项

2)public ObjectId UploadFromBytes(string filename, byte[] source, GridFSUploadOptions options = null, CancellationToken cancellationToken = null)

上传操作

参数:

  filename:文件名

  source:待上传资源

  options :上传选项

  cancellationToken :传播有关应取消操作的通知

3)public Task<ObjectId> UploadFromBytesAsync(string filename, byte[] source, GridFSUploadOptions options = null, CancellationToken cancellationToken

异步上传操作

参数同2)

4)public ObjectId UploadFromStream(string filename, Stream source, GridFSUploadOptions options = null, CancellationToken cancellationToken = null);

上传操作

参数同2)

4)public Task<ObjectId> UploadFromStreamAsync(string filename, Stream source, GridFSUploadOptions options = null, CancellationToken cancellationToken = null);

上传操作

参数同2)

5)public GridFSUploadStream OpenUploadStream(string filename, GridFSUploadOptions options = null, CancellationToken cancellationToken = null);

上传操作

参数:

  filename:文件名

  options :上传选项

  cancellationToken :传播有关应取消操作的通知

返回值:

  流,通过此流将数据写入GridFS

5)public byte[] DownloadAsBytes(BsonValue id, GridFSDownloadOptions options = null, CancellationToken cancellationToken = null);

下载操作

参数:

  id:文件id,注意这个是files_id的值,而不是_id的值

  options :下载选项

  cancellationToken :传播有关应取消操作的通知

7)public void DownloadToStream(BsonValue id, Stream destination, GridFSDownloadOptions options = null, CancellationToken cancellationToken = null);

下载操作

参数:

  id:文件id,注意这个是files_id的值,而不是_id的值

  destination:目标流

  options :下载选项

  cancellationToken :传播有关应取消操作的通知

8)public void DownloadToStreamByName(string filename, Stream destination, GridFSDownloadByNameOptions options = null, CancellationToken cancellationToken = null);

下载操作

参数:

  filename:文件名

  destination:目标流

  options :下载选项

  cancellationToken :传播有关应取消操作的通知

9)public IAsyncCursor<GridFSFileInfo> Find(FilterDefinition<GridFSFileInfo> filter, GridFSFindOptions options = null, CancellationToken cancellationToken = null);

查找操作

参数

  Filter:查询过滤器

  options :查找选项

  cancellationToken :传播有关应取消操作的通知

10)public void Delete(BsonValue id, CancellationToken cancellationToken = null);

删除一个文件

参数:

  id:文件id,注意这个是files_id的值,而不是_id的值

  cancellationToken :传播有关应取消操作的通知

11)public void Drop(CancellationToken cancellationToken = null);

删除整个chunks

12)public void Rename(BsonValue id, string newFilename, CancellationToken cancellationToken = null);

重命名操作

参数:

  id:文件id,注意这个是files_id的值,而不是_id的值

  newFilename:新文件名

  cancellationToken :传播有关应取消操作的通知

二、操作实例

GridFS简介

MongodB使用两个集合来存储GridFS文件,一个是fs.files,另一个是fs.chunks。

fs.files这个集合中存储的是每一个上传到数据库的文档的信息。

fs.chunks这个集合存储的是上传文件的内容。一个chunk相当于一个文档。

GridFS中的bucket这个概念指代的是fs.files和fs.chunks的组合。

使用Robmongo只能看到fs.files的部分结构为:

{

    "_id" : ObjectId("5a6559cd379d581bc00b0921"),

    "length" : NumberLong(25822),

    "chunkSize" : 261120,

    "uploadDate" : ISODate("2018-01-22T03:26:05.327Z"),

    "md5" : "03c50390b953913428daeb11c6a31b8f",

    "filename" : "gridfsTest"

}

其中

  _id:此文档唯一标识

  length:文件长度

  uploadDate:文件上传日期

  md5:完整文件的MD5

  filename:文件名

未列出的字段包括:

  contentType:字符串类型,文件的MIME类型

  aliases:数组类型,别名集合

  metadata:任意类型,用户想存入的附加信息

使用Robmongo查看fs.chunks的结构为:

{

    "_id" : ObjectId("5a656bf4379d5820fcd60412"),

    "files_id" : ObjectId("5a656bf4379d5820fcd60411"),

    "n" : 0,

    "data" : { "$binary" : "suLK1MnPtKvX1r3ayv3X6Q==", "$type" : "00" }

}

其中:

  _id:一个块(文档)的唯一标识。

  files_id:源文档的唯一标识,用来区别集合中的文件。

  n:块的序号,从0开始。GridFS中每一块的大小可以设定,默认是255KB,当上传的文件大于设定的或默认的块大小时,会将文件切分成几块进行存储,但最后一块可能比设定的值或默认值大。

    例如上传一个296KB的文件,默认块大小,发现包含两块,fs.chunks中的文当结构

而在fs.files中对应着一个文档,指明了上传文件的总大小

data:文件内容

客户端封装

说明:

展示部分代码段,对GridFS操作的封装大体相同,可根据实际情况修改。

调用方式统一采用:

    /// <summary>
    /// MongoDB操作
    /// </summary>
    public class MongoDBService
    {
        #region 变量
        /// <summary>
        /// 缓存
        /// </summary>
        private static ConcurrentDictionary<string, Lazy<MongoClient>> m_mongoClientCache = 
            new ConcurrentDictionary<string, Lazy<MongoClient>>();
        /// <summary>
        /// 连接字符串
        /// </summary>
        private string m_connectionStr = string.Empty;
        /// <summary>
        /// 数据库名称
        /// 支持运行时更改
        /// </summary>
        public string DatabaseName { get; set; }
        /// <summary>
        /// 设置GridFS参数
        /// </summary>
        public GridFSBucketOptions BucksOptions { get; set; }
        #endregion

       
        /// <summary>
        /// 初始化操作
        /// </summary>
        public MongoDBService(string connStr, string database)
        {
            m_connectionStr = connStr;
            DatabaseName = database;
        }

        /// <summary>
        /// 获得Mongo客户端
        /// </summary>
        /// <param name="connStr">连接串</param>
        /// <returns></returns>
        private static MongoClient GetClient(string connStr)
        {
            if (string.IsNullOrWhiteSpace(connStr)) throw new ArgumentException("MongoDB Connection String is Empty");

            return m_mongoClientCache.GetOrAdd(connStr,
                new Lazy<MongoClient>(() =>
                {
                    return new MongoClient(connStr);
                })).Value;
        }
    ......
        public ObjectId UploadFromBytes(byte[] source, string fileName, GridFSUploadOptions options=null)
        {
            MongoClient client = GetClient(m_connectionStr);
            var db = client.GetDatabase(DatabaseName);
            var bucket = new GridFSBucket(db, BucksOptions);
            return bucket.UploadFromBytes(fileName, source, options);
        }
    ......
}

1上传

//读取本地文件,然后上传
using (FileStream sr = new FileStream(@"D:\gridfsTest.jpg", FileMode.Open))
            {

                mongoDBService.UploadFromStream(sr, "gridfsTest", null);
            }
//上传字节数组
string str = "测试上传字节数组";
            byte[] b = Encoding.Default.GetBytes(str);
            mongoDBService.UploadFromBytes(b, "gridfsTest");
//换一种方式
mongoDBService.UploadToStream(b, "gridfsTest");

2下载

//写入本地文件
using(FileStream fs = new FileStream(@"D:\gridfsDownload.jpg", FileMode.Create))
            {
                mongoDBService.DownloadToStream(new ObjectId("5a61a113379d582f14e750a3"), fs);
            }

//获取文件内容
            var b = mongoDBService.DownloadAsBytes(new ObjectId("5a61b103379d5829f89d0688"));
            Console.WriteLine(Encoding.Default.GetString(b));

//异步方法
            var bs = mongoDBService.DownloadAsBytesAsync(new ObjectId("5a61b103379d5829f89d0688"));
            bs.Wait();
            Console.WriteLine("异步的方法,获得的字符串为:" + Encoding.Default.GetString(bs.Result));

//使用文件名下载
var options = new GridFSDownloadByNameOptions
            {
                Revision = 0//指定版本
            };
            using (FileStream fs = new FileStream(@"D:\gridfsDownloadByName.jpg", FileMode.Create))
            {
                mongoDBService.DownloadToStreamByName("gridfsTest", fs,options);
            }

3 查找

//可以选择排序方式
var filter = Builders<GridFSFileInfo>.Filter.Eq(x => x.Filename, "gridfsTestNewName1");
            var info = mongoDBService.Find(filter);

4重命名和删除

//改一个文件
            mongoDBService.RenameSingleFile(new ObjectId("5a61b103379d5829f89d0688"), "gridfsTestNewName");

            //全改
            var filter = Builders<GridFSFileInfo>.Filter.Eq(x => x.Filename, "gridfsTest");
            mongoDBService.RenameAllRevisions("gridfsTestNewName1", filter);
//删除指定的一个文件
            mongoDBService.DeleteSingleFile(new ObjectId("5a61a113379d582f14e750a3"));

            //删除整个chunks
            mongoDBService.DropEntireBucket();

5修改GridFSBucket参数

//注意ChunkSizeBytes 单位是byte
GridFSBucketOptions  bucksOptions = new GridFSBucketOptions 
{
      BucketName = "firstbucket",
      ChunkSizeBytes =1024,
};

Firstbucket为新的名称,默认的名称为fs

-----------------------------------------------------------------------------------------

时间仓促,水平有限,如有不当之处,欢迎指正。

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏安富莱嵌入式技术分享

【RL-TCPnet网络教程】第32章 RL-TCPnet之Telnet服务器

本章节为大家讲解RL-TCPnet的Telnet应用,学习本章节前,务必要优先学习第31章的Telnet基础知识。有了这些基础知识之后,再搞本章节会有事半功倍的...

653
来自专栏沃趣科技

MySQL中server_id一致带来的问题

简 介 我们都知道在MySQL搭建复制环境的时候,需要设置每个server的server_id不一致,如果主库与从库的server_id一致,那么复制会失败。...

3366
来自专栏大内老A

[WCF 4.0新特性] 默认终结点

很多WCF的初学者是从之前的Web服务上转移过来的,他们非常怀念.asmx Web服务无配置的服务寄宿方式。你只需要在定义Web服务的时候再表示服务操作的方法上...

1785
来自专栏数据库新发现

Emulex光纤卡lpfc配置文件的修改

# cd /kernel/drv # vi sd.conf "sd.conf" 65 lines, 1611 characters # # Copyright...

1032
来自专栏听雨堂

Log4Net使用心得

winform程序使用Log4net   1.引用dll   2.添加log4net.config,设置“始终复制”   4.assemblyinfo.cs中添...

18710
来自专栏熊二哥

Redis快速入门

由于工作慢慢从原来的少量用户的企业内部应用慢慢转化为了大量用户的企业内部应用或者直接转为了线上高并发应用,因而也渐渐的开始使用memcached、Redis等缓...

19710
来自专栏Android 研究

Android跨进程通信IPC之5——Binder的三大接口

本片文章的主要目的是让大家对Binder有个初步的了解,既然是初步了解,肯定所是以源码上的注释为主,让大家对Binder有一个更直观的认识。PS:大部分注释我是...

985
来自专栏木宛城主

迁移TFS,批量将文档导入SharePoint 2013 文档库

一、需求分析 公司需要将存在于旧系统(TFS)所有的文档迁移至新系统(SharePoint 2013)。现已经将50G以上的文档拷贝到SharePoint ...

18510
来自专栏一个爱瞎折腾的程序猿

winform制作小工具的技巧

在使用winfrom制作一些工具的时候,一些基本设置都是去属性里面找来找去,一段时间就忘了,记录记录以备不时之需。

1023
来自专栏fixzd

redis系列:通过日志案例学习string命令

该文章将通过一个小demo将讲述Redis中的string类型命令。demo将以springboot为后台框架快速开发,iview前端框架进行简单的页面设计,为...

1004

扫码关注云+社区