GridFS是MongoDB存储超16MB文件的唯一官方机制,因其将大文件分块存入fs.chunks并存元数据于fs.files,规避单文档16MB限制;普通文档存储会触发BSON大小错误或数据截断。
GridFS 是 MongoDB 唯一能直接存取超过 16 MB 文件的官方机制,AI 模型(如 PyTorch
、TensorFlow
或 ONNX
)动辄几百 MB 甚至数 GB,必须用 GridFS,别想绕开。
为什么不能用普通文档存模型文件
MongoDB 单文档硬性限制为 16 MB。尝试用
直接塞进一个文档会触发
错误;即使压缩后勉强压到 16 MB 内,后续更新、校验、分片迁移都会出问题——它不是为大二进制设计的。
常见错误现象:
插入时报错:
用
成功但查不到完整内容,驱动自动截断
用
能看到元数据,
却为空——说明上传根本没走 GridFS 流程
创建 GridFSBucket 时必须指定 bucketName
默认 bucket 名是
,但生产环境强烈建议自定义,比如
。否则所有项目共用同一套
/
,元数据混杂、删除风险高、权限难隔离。
实操建议:
Spring Boot 中配置:
Node.js 中:
Python PyMongo:
务必确认
和
两个集合存在且有索引(驱动会在首次写入时自动建,但需检查是否成功)
上传模型文件必须用流式接口,不能用 uploadFromStream 的简写变体
看似方便,但它把整个文件读进内存再分块,对 >500 MB 的模型极易 OOM。真正安全的做法是用
+ 可读流管道。
以 Python 为例:
go语言参考手册 中文CHM版
Go 是一个开源的编程语言,它能让构造简单、可靠且高效的软件变得容易。本文给大家带来Go参考手册,需要的可以来下载! Go是从2007年末由Robert Griesemer, Rob Pike, Ken Thompson主持开发,后来还加入了Ian Lance Taylor, Russ Cox等人,并最终于2009年11月开源,在2012年早些时候发布了Go 1稳定版本。现在Go的开发已经是完全开放的,并且拥有一个活跃的社区。 Go 语言特色 简洁、快速、安全 并行、有趣、开源 内存管理、v数组安全、编译
下载
关键点:
不要依赖
——
仍会全量加载
字段必须包含可检索字段(如
、
),否则后续无法按条件找模型
块大小默认 255 KiB,无需改;改了反而影响跨语言兼容性
下载和加载模型时要避免一次性 read() 到内存
模型文件大,
或
后调
容易爆内存。正确做法是边流式读、边送入模型加载器。
例如 PyTorch 场景:
注意:
返回的是类似文件对象的流,支持
、
,但
仅限于已缓存块,随机跳转大模型不现实
若需校验 hash,应在上传时存入
,下载后用流式计算比对,别等全读完再算
不要在 Web API 中直接返回 GridFS 文件流给前端——没有 Content-Length,HTTP 分块传输易中断;应先落盘或用 Nginx X-Accel-Redirect
最容易被忽略的是元数据设计:很多团队只存
,结果版本回滚、A/B 测试、灰度发布全靠人工翻日志。真正要用起来,
至少得有
、
、
、
这四样——它们决定了你能不能在 3 秒内切回上个稳定模型。
.pt.h5.onnxBinDataBSONObj size too largeDocument is larger than 16777216 bytesinsertOne()fs.filesfs.chunksfsmodelsfs.filesfs.chunksGridFSBucket bucket = GridFSBuckets.create(database, "models")const bucket = new mongodb.GridFSBucket(db, { bucketName: 'models' })bucket = gridfs.GridFSBucket(db, bucket_name='models')models.filesmodels.chunksuploadFromStream()openUploadStream()with open("model.pt", "rb") as f:
gridfs_file = bucket.open_upload_stream(
filename="resnet50_v2_202604.pt",
metadata={
"version": "202604",
"framework": "pytorch",
"hash": "sha256:abc123...",
"size_bytes": os.path.getsize("model.pt")
}
)
while chunk := f.read(1024 * 1024): # 每次读 1MB
gridfs_file.write(chunk)
gridfs_file.close()
file_id = gridfs_file._id
uploadFromStream(filename, io.BytesIO(...))BytesIOmetadataversionframeworkdownload_to_stream()find_one().read()grid_out = bucket.open_download_stream(file_id)
# 直接传给 torch.load,不经过中间 buffer
model = torch.load(grid_out, map_location="cpu")
open_download_stream()read()seek()seek()metadatafilenamemetadataversioncommit_hashtrain_timeinput_shape