GridFS 获取文件原始内容必须用 openDownloadStream() 返回可读流,传入 ObjectId 类型 _id,禁止全量加载;需设 Content-Type 和 Content-Disposition: inline 响应头,并校验 MIME 类型白名单以保障安全。

GridFS 本身不提供文件预览能力,必须结合文件类型解析、流式读取和前端适配来实现——核心是把 fs.files 和 fs.chunks 中的二进制数据按需解包并转成浏览器可渲染格式。
怎么用 GridFS 获取文件原始内容?
不能直接查 fs.files 表拿到完整文件;得用官方驱动的 GridFSBucket 或 GridFSBucketOpenUploadStream 对应的读取接口。Node.js 中最稳妥的是 openDownloadStream(),它返回一个 Readable 流,支持管道(pipe)或分块消费。
- 必须传入
_id(ObjectId类型)或filename,后者在有重名时可能返回第一个匹配项 - 若文件较大(如 >10MB),别用
toArray()或toString()全量加载到内存,容易 OOM - 对 PDF、图片等二进制文件,直接 pipe 到响应体即可;但文本类(如 .txt、.log)建议设
encoding: 'utf8'避免乱码
为什么 PDF 预览常显示 “Failed to load PDF document”?
常见原因是响应头缺失或不匹配。GridFS 返回的是原始二进制流,但浏览器 PDF 查看器(如内置 PDF.js)要求严格的 Content-Type 和 Content-Disposition。
- 必须显式设置
res.setHeader('Content-Type', 'application/pdf'),不能依赖自动推断 - 如果用
attachment模式(Content-Disposition: attachment; filename="x.pdf"),部分浏览器会强制下载而非内嵌预览;改用inline才能触发 PDF.js 渲染 - 某些 Nginx 或反向代理会缓存或截断流响应,需确认代理配置中禁用
proxy_buffering并设置proxy_http_version 1.1
如何安全地支持多种文件类型预览?
不能无差别返回所有文件——可执行文件、压缩包、数据库文件等必须拦截,否则存在安全风险。关键靠三步校验:
- 查
fs.files文档中的contentType字段(写入时应主动设置),优先以此为准;若为空,再用file-type库从流前若干字节识别 MIME 类型 - 维护白名单:只允许
image/*、text/*、application/pdf、application/vnd.openxmlformats-officedocument.*等已知安全类型 - 对 Office 文档(.docx/.xlsx),浏览器无法原生渲染,需调用 LibreOffice 或 OnlyOffice 转 PDF,或前端用
mammoth、xlsx等库解析,不能直接返回原始流
真正麻烦的不是读取,而是类型判定和响应头控制——很多问题都出在 contentType 字段写入不规范,或者代理层吞掉了流首部字节,导致 MIME 推断失败。预览逻辑上线前,务必用 curl -I 验证响应头是否符合预期。


















