1 GridFS 简介
当前 Bson 能存储的最大尺寸是 16M, 我们想把大于 16M 的文件存入 MongoDB 中怎么办呢? MongoDB 提供的 GridFS 就是专门做这个的. 使用 GridFS 存储大文件时, 文件被分成一个个的块(默认大小是 255 kb), 将每一块存放在一个单独的 document 中. GridFS 将文件存储在两个 collection 中: chunks collection 和 files collection, 其中 chunks collection 保存文件块, files collection 保存文件的元数据.
2 使用 mongofiles 进行大文件管理
mongofiles 是 MongoDB 内置的文件操作工具, 提供了十分简单的 API 让我们可以通过命令行实现文件的上传, 下载, 查找和删除. 我们使用一个视频文件做测试.
1 上传文件(put)
这里准备将 / data/videos 下的电影绿皮书 (文件名:"lvpishu.mkv") 上传到 MongoDB 数据库 myfiles 中下, 只需要使用一条命令就可以完成文件的上传: 在 MongoDB 的 bin 目录下执行命令 mongofiles -d myfiles -l /data/videos/lvpishu.mkv put lvpishu.mkv . 上传完成后使用 robomongo 查看文件信息, 如下:
使用 robomongo 查看上传的文件信息, 如下图:
2 下载文件(get)
下载 GridFS 中的文件使用命令 Get, 如我们要将刚才上传的电影, 下载到 / data/videos2 目录下, 执行命令 mongofiles -d myfiles -l /data/videos2/lvpishu.mkv get lvpishu.mkv 即可, 效果如下:
3 查找文件(list,search)
查询 GridFS 中的文件可以使用 search 查询文件名包含某字符串的文件信息, 使用 list 查询以某字符串开头的文件列表, 因为我们只上传了一个文件所以这里的文件列表也只展示一条文件信息, 执行命令效果如下:
4 删除文件(delete)
如果我们想删除 GridFS 中的某一文件, 使用 delete <filename > 命令
3 使用 C# 驱动操作 GridFS
前边我们已经使用 MongoDB 自带的命令行工具 mongofiles 实现了大文件的增删查操作, 但是实际开发中我们更常用的方式是使用各种语言驱动来管理文件, 这里展示怎么通过 C# 驱动来实现大文件的管理. 添加 GridFS 的包 Install-Package MongoDB.Driver.GridFS ,C# 驱动中提供了 GridFSBucket(GridFS 桶)对象来保存文件, 它是 fs.files 和 fs.chunks 的组合, 我们在使用时, 最好使用 GridFSBucket 来和 GridFS 交互, 尽量不要直接使用底层的 fs.files 和 fs.chunks).
- C# 驱动 MongoDB 的上传和下载文件有两种形式:1通过字节数组 byte[]上传和下载, 这种方式适用于文件不大的情况,2使用 stream 的方式进行上传和下载, 这种形式适用于各种场合, 这里就采用 stream 的形式做文件的上传和下载演示, 代码如下:
- class Program
- {
- static void Main(string[] args)
- {
- // 连接数据库
- var client = new MongoClient("mongodb://192.168.70.133:27017, 192.168.70.131:27017, 192.168.70.129:27017");
- // 获取 database
- var mydb = client.GetDatabase("myfilesDb");
- // 初始化 GridFSBucket
- var bucket = new GridFSBucket(mydb, new GridFSBucketOptions
- {
- BucketName = "lvpishu", // 设置根节点名
- ChunkSizeBytes = 1024 * 1024, // 设置块的大小为 1M
- WriteConcern = WriteConcern.WMajority, // 写入确认级别为 majority
- ReadPreference = ReadPreference.Secondary // 优先从从节点读取
- });
- // 上传文件
- // 上传的配置项, 可以添加文件元数据
- var options = new GridFSUploadOptions
- {
- //ChunkSizeBytes = 1048000,
- Metadata = new BsonDocument
- {
- { "format", "mkv" },
- { "country", "USA" }
- }
- };
- // 通过 stream 形式上传文件
- ObjectId fileId;
- Console.WriteLine("开始文件上传 ---------------->");
- string sourceFile = @"D:\ 迅雷下载 \ lvpishu.mkv";
- using (var fs = new FileStream(sourceFile, FileMode.Open))
- {
- //MongoDB 中的文件名为 "绿皮书"
- Console.WriteLine("上传中...");
- fileId = bucket.UploadFromStream(filename: "绿皮书", source: fs, options: options);
- }
- Console.WriteLine("<---------------- 文件上传完成");
- Console.WriteLine();
- // 查看文件
- var filter = Builders<GridFSFileInfo>.Filter;
- using (var cursor = bucket.Find(filter.Eq(x => x.Filename, "绿皮书")))
- {
- var fileInfo = cursor.FirstOrDefault();
- fileId = fileInfo.Id;
- Console.WriteLine($"文件名:{fileInfo?.Filename}, 文件大小:{fileInfo?.Length}字节, 文件上传时间:{fileInfo?.UploadDateTime.AddHours(8)}");
- Console.WriteLine($"自定义的元数据:{fileInfo?.Metadata}");
- }
- Console.WriteLine();
- // 下载文件
- // 文件下载的位置
- Console.WriteLine("开始文件下载 ---------------->");
- string tagrgetPath = @"D:/mongoDownLoad / 绿皮书下载. mkv";
- using (var mongoStream = bucket.OpenDownloadStream(id: fileId))
- {
- Console.WriteLine("下载中...");
- // 通过 FileStream 写文件
- using (FileStream fsWrite = new FileStream(tagrgetPath, FileMode.Create))
- {
- // 开辟临时缓存内存
- byte[] buffer = new byte[1024 * 1024];
- while (true)
- {
- //readCount 是真正读取到的字节数
- int readCount = mongoStream.Read(buffer, 0, buffer.Length);
- // 写入目标文件
- fsWrite.Write(buffer, 0, readCount);
- // 判断是否读取完成
- if (readCount < buffer.Length)
- {
- break;
- }
- }
- }
- }
- // 最好比较一下 MongoDB 中的文件和下载文件的 Md5 值, 如果 md5 相同表示下载完成
- // 这里为了简单起见, 就简单判断以下文件是否存在
- if (File.Exists(@"D:/mongoDownLoad / 绿皮书下载. mkv"))
- {
- Console.WriteLine("<---------------- 文件下载完成!");
- }
- Console.WriteLine();
- // 删除文件
- bucket.Delete(id: fileId);
- Console.WriteLine("文件已删除!");
- Console.ReadKey();
- }
- }
初始化 GridFSBucket 时可以设置一些参数: BucketName 用于设置 files 和 chunks 的根节点名, 如设置 BucketName="lvpishu", 那么在数据库中保存文件的两个 collection 的名字为 lvpishu.files 和 lvpishu.chunks.ChunkSizeBytes 用于设置数据块的大小, 这里设置数据块大小为 1M.
代码的注释比较详细, 这里就不多介绍了, 程序运行结果如下:
小结
本节介绍了 GridFS 的概念, 并简单演示了怎样使用 mongofile 和 C# 驱动进行大文件的上传, 查询, 下载, 删除操作. 如果文中有错误的话, 希望大家可以指出, 我会及时修改, 谢谢!
来源: https://www.cnblogs.com/wyy1234/p/11048130.html