连错数据库导致fs.list()返回空列表,根本原因是GridFS实例绑定的数据库对象错误,实际操作了默认test库而非目标库,需显式传入正确database对象并验证db.fs.files.countDocuments({})>0。

连错数据库导致 fs.list() 返回空列表
这是最常踩的坑:fs.list() 看起来没报错,但返回空列表,而你确认库里明明有文件。根本原因不是 GridFS 没数据,而是 GridFS 实例绑定的数据库对象不对。
- GridFS 依赖两个集合:
fs.files和fs.chunks,它们属于你显式指定的数据库;如果只用MongoClient连接但没传db = client["your_db_name"],它默认操作的是test库(哪怕连接串里写了/mydb) - 务必先在
mongosh里执行use your_db_name再运行db.fs.files.countDocuments({}),确认数字 > 0 - Python 中必须显式传入
database对象:fs = gridfs.GridFS(db),不能写成fs = gridfs.GridFS(client)或fs = gridfs.GridFS(client["your_db_name"])(后者虽能运行,但易因 client 复用出错)
fs.find({}) 才能拿到全部文件,fs.get_last_version() 只取最新版
如果你只用 fs.get_last_version("report.pdf"),会漏掉同名历史版本——GridFS 允许同一 filename 多次上传,每次生成新文档存进 fs.files,靠 uploadDate 排序。
-
fs.find({})返回游标,遍历它才能拿到所有文件文档(含_id、filename、uploadDate、metadata) - 不要直接用
file_obj.filename当本地文件名:含/、:、*会触发OSError: [Errno 22] - 清洗建议:
re.sub(r'[:"/\|?*]', "_", file_obj.filename)(注意 Windows 路径分隔符是反斜杠) - 大文件(>10MB)别一次性
read():用iter(lambda: grid_out.read(8192), b"")分块读,避免内存溢出
用 mongofiles 批量导出时文件名含空格或中文就失败
mongofiles list 输出带制表符和多余空格,xargs 一碰就截断;文件名含中文、括号、空格时,mongofiles get "a b.jpg" 仍可能解析失败——它内部对 shell 字符转义支持极弱。
- 唯一靠谱做法:
mongofiles list --quiet | while IFS= read -r f; do mongofiles get "$f" && mv "$f" "export_$(date +%s%N)_$f"; done -
--quiet是关键:去掉头尾提示和制表符,每行纯文件名 - 不加双引号的
$f在空格处直接裂开;不重命名就覆盖——同名文件多次上传后,get总是取最新版,旧版彻底丢失 - 它不暴露
_id,无法按 ID 精确下载;也不支持并发、断点续传、跳过已存在文件
用 mongodump 导出 fs.files 和 fs.chunks 集合只是备份,不是“导出文件”
mongodump --collection fs.files 只导出元数据 JSON/BSON,fs.chunks 导出的是二进制分块数据,两者合起来才是完整文件——但你没法直接用系统命令把它们拼成 JPG 或 PDF。
- 这种导出适合跨环境迁移 GridFS 数据库,比如从测试库迁到生产库
- 想还原成可查看的本地文件?还得写脚本:读
fs.files文档 → 拿_id→ 查fs.chunks中所有files_id匹配的块 → 按n字段排序拼接 → 写入文件 - 比直接用
pymongo+GridFSAPI 多绕三步,还容易因 chunk 缺失或顺序错乱导致文件损坏

















