GridFS操作须通过mongo.Database.GridFSBucket()获取bucket实例,不可直接import旧gridfs包或手动构造;上传需用io.Reader并设ChunkSizeBytes,下载须用io.Copy避免OOM。

GridFS在mongo-driver中没有独立gridfs包
Go官方mongo-driver(v1.10+)早已移除了单独的gridfs子包。你搜到的旧教程里用的go.mongodb.org/mongo-driver/mongo/gridfs在v1.5之后就已废弃,现在所有GridFS操作都统一收归到go.mongodb.org/mongo-driver/x/mongo/driver/gridfs——但它不是公开API,**不能直接import**。正确路径是通过mongo.Database的GridFSBucket()方法获取*gridfs.Bucket实例。
常见错误现象:cannot find package "go.mongodb.org/mongo-driver/mongo/gridfs" 或运行时报undefined: gridfs.NewBucket。这是因为你用了过时导入路径,或试图手动构造Bucket。
- 必须先确保引入的是最新驱动:
go get go.mongodb.org/mongo-driver/mongo@latest -
GridFSBucket()是*mongo.Database的方法,不是独立构造函数 - 底层依赖
x/mongo/driver/gridfs会被自动间接引入,无需显式import
初始化Bucket要传对数据库和选项
GridFS本质是把大文件切块存进fs.chunks和fs.files两个集合,所以GridFSBucket()必须绑定明确的*mongo.Database,且默认使用"fs"作为前缀。如果服务端用的是自定义集合名(比如"uploads.chunks"),就得靠gridfs.Options改。
容易踩的坑:不设BucketOptions就以为能自动适配已有集合;或者误把Database对象当成Client传进去导致panic。
立即学习“go语言免费学习笔记(深入)”;
- 基础初始化:
bucket := db.GridFSBucket()—— 使用fs.files/fs.chunks - 自定义集合前缀:
bucket := db.GridFSBucket(&gridfs.Options{BucketName: "uploads"})→ 对应uploads.files/uploads.chunks - 指定编码器(如需自定义元数据结构):
&gridfs.Options{Encoder: bson.NewEncoder(...)},但99%场景用默认即可
上传文件时别直接传*os.File,要用io.Reader
bucket.UploadFromStream()第二个参数要求io.Reader,不是*os.File。虽然*os.File实现了io.Reader,但直接传会导致文件指针位置错乱(尤其多次调用时),且无法控制缓冲大小。
典型问题:上传后文件内容为空、长度对不上、或并发上传时出现read: connection reset by peer。
- 安全做法:用
bytes.NewReader(data)(小文件)、bufio.NewReader(f)(大文件)、或直接传http.Request.Body - 务必设置
gridfs.UploadOptions里的ChunkSizeBytes(默认255KB)。上传GB级视频时建议设为1024 * 1024 * 4(4MB),减少chunk文档数量 - 元数据写进
Options.Metadata字段(bson.M类型),不要塞进文件名——文件名只用于_id生成逻辑
下载大文件必须用DownloadToStream,避免内存爆炸
bucket.DownloadByID()返回*gridfs.File,它实现了io.ReadCloser,但**不能直接io.ReadAll()**。一旦文件超100MB,进程内存会飙升,还可能触发OOM kill。
真实场景里,用户下载PDF/视频,后端得边读边写响应体,而不是全载入内存再吐出去。
- 正确姿势:
file, _ := bucket.DownloadByID(ctx, fileID); defer file.Close(); io.Copy(responseWriter, file) - 需要校验MD5?用
file.GetMD5(),它从files集合的md5字段取,不重新计算 - 查不到文件时,
DownloadByID返回nil, mongo.ErrNoDocuments,不是nil错误——记得用errors.Is(err, mongo.ErrNoDocuments)判断
GridFS不是万能存储层,小文件(

















