把图片、视频、安装包这类大文件塞进MongoDB,标准做法就是GridFS。它把文件切分成多个chunk存进集合,再通过元数据管理文件信息。不过很多人写代码调GridFS API之前,忽略了MongoDB自带了一个命令行工具mongofiles,不需要写一行代码就能完成文件的上传、下载、删除和列表查询,在排查问题或者临时传文件的场景下特别好用。本文从GridFS的存储结构讲起,把mongofiles的常用命令和参数逐一演示一遍。

GridFS的存储原理先弄明白
GridFS并不是MongoDB的一个独立功能,而是一种使用规范。它依赖两个集合协同工作:一个叫fs.files,负责存文件的元数据,包括文件名、长度、上传时间、MD5值等;另一个叫fs.chunks,存的是真正的文件内容。当一个文件被写入GridFS时,驱动会把它切成若干个块,默认每块大小为255KB,每个块对应fs.chunks里的一条文档,文档中有一个files_id字段指向fs.files里的记录,还有一个n字段标记这是第几块。
这么设计的好处很明显。第一,MongoDB单条文档有16MB的大小限制,直接把大文件塞进一个文档肯定不行,切块之后就没有这个限制了;第二,读取文件时可以按块流式读取,不必把整个文件加载进内存,对内存非常友好;第三,文件元数据和内容分开存储,查找文件列表时只查fs.files,速度快得多。
还有一点值得注意,fs只是默认前缀。GridFS允许使用不同的前缀把文件分类存到不同的集合对里,比如前缀设成video,对应的就是video.files和video.chunks。后面讲mongofiles参数时会提到怎么指定前缀。
mongofiles基础用法:连接数据库并上传文件
mongofiles是MongoDB数据库工具包的一部分,安装MongoDB服务端或者单独下载数据库工具包后,在bin目录下就能找到它。它的基本语法结构是mongofiles [选项] [子命令] [文件名],连接参数和mongo shell类似,用--host指定主机、--port指定端口、-u和-p指定账号密码、-d指定目标数据库。
p>最常用的子命令是put,用来把本地文件上传到GridFS。比如连接本机test库并上传一个文件:mongofiles --host 127.0.0.1 --port 27017 -d test put D:\backup\logo.png
执行成功后终端会输出文件的元数据信息,包括_id、文件名、长度和chunk数量。注意Windows环境下路径的反斜杠要原样保留,比如D:\backup\logo.png这种写法可以直接使用。如果想验证结果,可以用list子命令查看库里的文件列表:
mongofiles -d test list 2024-01-15T10:32:11.567+0800 connected to: mongodb://127.0.0.1:27017/ logo.png 45231 photo.jpg 1024876
list后面的数字是文件字节大小。如果库里存在同名文件,GridFS不会覆盖旧文件,而是新插入一条fs.files记录,两个版本并存,下载时默认取最新版本,也可以通过--revision参数指定旧版本,这一点在文件需要保留历史版本时很有用,但也容易造成存储膨胀,要留意清理。
下载、删除和查找文件的操作细节
下载文件用get子命令。最直接的用法是按文件名下载,文件会保存到当前工作目录:
cd C:\Users\admin\Downloads mongofiles -d test get logo.png
如果想把文件下载到指定路径,或者按_id精确下载,可以用search子命令配合或者直接指定ObjectId。get_id子命令接收文件的_id值:
mongofiles -d test get_id 652e1f8a3b4d5e6f7a8b9c0d
这里有个容易踩的坑:当数据库中存在多个同名文件时,按文件名get拿到的是最新上传的那个版本。如果业务上需要精确控制,建议始终用_id来下载,避免版本混乱。search子命令支持模糊查找,参数是一个正则表达式风格的模式,比如search photo会列出所有名字里包含photo的文件。
删除用delete子命令,注意它会删除所有同名文件的记录,包括历史版本:
mongofiles -d test delete logo.png
如果只想删某一个版本,还是得借助_id,用delete_id。删除操作本身没有确认提示,执行前务必核对文件名,生产环境建议先用search确认范围再动手。
进阶参数与常见问题排查
几个实用参数值得记住。--prefix可以指定集合前缀,默认是fs,如果文件当初是以前缀media上传的,用mongofiles操作时必须带上--prefix media,否则会提示找不到文件,这是实际使用中最高频的一个疑问。--local用于显式指定本地文件路径,配合put和get使用,可以避免先切换目录的麻烦。认证场景下记得加--authenticationDatabase,账号一般建在admin库,否则会出现认证失败的报错。副本集环境建议加上--host参数写成副本集名称加成员列表的形式,驱动会自动找主节点。
mongofiles --host rs0/mongo1.example.net:27017,mongo2.example.net:27017 -d files -u admin -p secret --authenticationDatabase admin --prefix media put C:\data\video.mp4
排查问题时,可以直接查元数据集合确认文件状态。用mongo shell连上库,查fs.files看文件的length、chunkSize和上传时间,再用files_id关联查fs.chunks,核对块数量是否和文件长度对得上。如果下载下来的文件打不开,多半是版本取错了,或者prefix不对导致get到了别的文件。
另外提一句性能方面的经验:mongofiles适合运维操作和临时调试,如果是应用程序高频读写文件,还是应该走驱动的GridFS API,因为命令行每次执行都要重新建立连接和认证,开销不小。把两者结合着用,日常开发调驱动,排查问题用命令行,效率会高很多。
MongoDB GridFSGridFS命令行mongofiles修改时间:2026-09-03 12:20:53