gridfs在.net中已被官方弃用,应避免使用gridfsbucket存小文件;推荐客户端分块、服务端按chunkindex顺序写入独立文档,并用objectid标识,配合原子操作更新元数据,迁移旧数据需脚本重写而非依赖驱动兼容。

GridFS在.NET中已被官方弃用,别再用GridFSBucket存小文件
从MongoDB.Driver 2.19开始,GridFSBucket类标记为[Obsolete],官方明确建议:小文件(byte[]字段存储;大文件才考虑自定义分块逻辑或迁移到对象存储。强行用GridFSBucket会导致升级受阻、缺乏维护、且无法享受新驱动的连接池优化和异步改进。
小文件直接存进文档,比GridFS更简单可靠
绝大多数场景——用户头像、配置文件、日志片段、JSON Schema模板——体积都在几KB到几MB之间。这类数据塞进普通集合比走GridFS更轻量、更易查询、更利于索引和备份。
-
byte[]字段可直接序列化进BSON,驱动自动处理Base64编码和二进制类型映射 - 配合
[BsonIgnoreIfNull]或[BsonDefaultValue(null)]控制空值行为 - 查询时能用
Filter.Eq("metadata.filename", "xxx")等条件联合检索,无需额外元数据集合关联 - 不依赖
fs.chunks/fs.files两套集合,避免跨集合事务缺失带来的不一致风险
var doc = new {
Id = ObjectId.GenerateNewId(),
Filename = "report.pdf",
ContentType = "application/pdf",
Data = File.ReadAllBytes("report.pdf")
};
await collection.InsertOneAsync(doc);
真要处理超大文件?自己分块+校验,别碰GridFSBucket
如果必须支持>100MB的上传(比如视频原始素材),GridFSBucket的默认分块策略(255KB/chunk)和MD5校验已过时,且不支持断点续传。更可控的做法是:客户端分块、服务端按chunkIndex顺序写入独立文档、用ObjectId做唯一标识、最后用原子操作更新主元数据。
- 每个分块存为独立文档,字段含:
fileId(关联主记录)、chunkIndex(int)、data(byte[])、checksum(SHA256) - 主记录含总大小、分块数、最终校验和,用
FindOneAndReplace带IsUpsert = true确保幂等 - 读取时用
Sort.By("chunkIndex")+ToListAsync()拼接,比GridFS的两次查询(先查files再查chunks)更直观 - 避免使用
GridFSBucket.OpenUploadStream——它内部仍调用已弃用API,且无法拦截每个chunk做预处理(如压缩、加密)
迁移旧GridFS数据?用mongodump + 脚本重写,别指望驱动兼容
现有fs.files和fs.chunks数据不能靠新版驱动自动转换。硬切会导致读失败或乱码,因为新驱动对_id类型、chunkSize字段解析逻辑已变更。
- 用
mongodump --db yourdb --collection fs.files --out ./backup导出元数据 - 写C#脚本遍历
fs.files文档,对每个_id执行collection.Find(Builders<bsondocument>.Filter.Eq("files_id", fileId))</bsondocument>拉取所有chunk - 拼接后存入新集合,字段名改为
content而非data,去掉uploadDate等冗余字段 - 过程中校验
length与实际字节总数是否一致,跳过损坏块(GridFSBucket本身也不报错)
真正麻烦的不是代码,是存量数据的完整性验证和业务侧缓存失效策略——这点容易被忽略。











