You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Node.js GridFS代码迁移后出现findOne未定义错误求助

问题

我有一个从MongoDB通过GFS获取图片的方法,在主app.js中运行正常,但移到单独文件夹后返回错误:

TypeError: Cannot read properties of undefined (reading 'findOne')

相关代码

图片模型文件(images/mongoose.js)

const mongoose = require('mongoose');
const mongoURI = process.env.MONGOURI;
const crypto = require("crypto");
const multer = require("multer");
const {GridFsStorage} = require("multer-gridfs-storage");
const Grid = require("gridfs-stream");
const path = require('path');


const conn = mongoose.createConnection(mongoURI);

//Init gfs
let gridfsBucket; 

let gfs = conn.once('open', () => {
  gridfsBucket = new mongoose.mongo.GridFSBucket(conn.db, {
  bucketName: 'uploads'
});

  gfs = Grid(conn.db, mongoose.mongo);
  gfs.collection('uploads');
  return gfs;
})



//create Storage engine
const storage = new GridFsStorage({
  limits: { fileSize: 5 * 1000 * 1000 },
  url: mongoURI,
  file: (req, file) => {
    return new Promise((resolve, reject) => {
      crypto.randomBytes(8, (err, buf) => {
        if (err) {
          return reject(err);
        }
        const filename = buf.toString('hex') + path.extname(file.originalname);
        const fileInfo = {
          filename: filename,
          bucketName: 'uploads'
        };
        resolve(fileInfo);
      });
    });
  }
});
const upload = multer({ storage });


module.exports = {
    upload,
    gridfsBucket,
    gfs,
    conn
}

获取图片路由

const {gridfsBucket} = require('../models/mongoose');
const gfs = require('../models/mongoose');


  exports.getImg = (req, res) => {
    console.log(`req file name is: ${req.params.filename}`);
    gfs.files.findOne({filename: req.params.filename}, (err, file) => {

      //Check if file exist
      if(!file || file.length === 0) {
        return res.status(404).json({
          err: "No file exist"
        });
      } 
        // Check if image
      if(file.contentType === "image/jpeg" || file.contentType === "image/png" || file.contentType === "image/jpg" || file.contentType === "image/heic") {
        //Read output to client
        const readstream = gridfsBucket.openDownloadStreamByName(file.filename);
        readstream.pipe(res);
      } else {
        res.status(404).json({err: "Not an image"});
      }
    });
  };

错误栈

TypeError: Cannot read properties of undefined (reading 'findOne')
    at exports.getImg (/Users/dordadon/Desktop/Full stack course/NerZikaron/controllers/system.js:136:15)
    at Layer.handle [as handle_request] (/Users/dordadon/Desktop/Full stack course/NerZikaron/node_modules/express/lib/router/layer.js:95:5)
    at next (/Users/dordadon/Desktop/Full stack course/NerZikaron/node_modules/express/lib/router/route.js:144:13)
    at Route.dispatch (/Users/dordadon/Desktop/Full stack course/NerZikaron/node_modules/express/lib/router/route.js:114:3)
    at Layer.handle [as handle_request] (/Users/dordadon/Desktop/Full stack course/NerZikaron/node_modules/express/lib/router/layer.js:95:5)
    at /Users/dordadon/Desktop/Full stack course/NerZikaron/node_modules/express/lib/router/index.js:284:15
    at param (/Users/dordadon/Desktop/Full stack course/NerZikaron/node_modules/express/lib/router/index.js:365:14)
    at param (/Users/dordadon/Desktop/Full stack course/NerZikaron/node_modules/express/lib/router/index.js:376:14)
    at Function.process_params (/Users/dordadon/Desktop/Full stack course/NerZikaron/node_modules/express/lib/router/index.js:421:3)
    at next (/Users/dordadon/Desktop/Full stack course/NerZikaron/node_modules/express/lib/router/index.js:280:10)

解决方案

问题根源

  1. 异步初始化导致变量未赋值:gfs和gridfsBucket是在数据库连接成功后才赋值的,但模块导出时这两个变量仍为undefined,路由加载时直接使用会报错。
  2. 路由导入错误:const gfs = require('../models/mongoose')导入的是整个模块对象,不是模块内的gfs属性,导致gfs.files为undefined。

修改后的代码

1. 修正模型文件(images/mongoose.js)

用Promise封装异步初始化逻辑,确保连接完成后再返回实例:

const mongoose = require('mongoose');
const mongoURI = process.env.MONGOURI;
const crypto = require("crypto");
const multer = require("multer");
const {GridFsStorage} = require("multer-gridfs-storage");
const Grid = require("gridfs-stream");
const path = require('path');

const conn = mongoose.createConnection(mongoURI);

let gridfsBucket; 
let gfs;

// 用Promise封装GFS初始化过程
const initGfs = new Promise((resolve) => {
  conn.once('open', () => {
    gridfsBucket = new mongoose.mongo.GridFSBucket(conn.db, {
      bucketName: 'uploads'
    });

    gfs = Grid(conn.db, mongoose.mongo);
    gfs.collection('uploads');
    resolve({ gfs, gridfsBucket });
  });
});

const storage = new GridFsStorage({
  limits: { fileSize: 5 * 1000 * 1000 },
  url: mongoURI,
  file: (req, file) => {
    return new Promise((resolve, reject) => {
      crypto.randomBytes(8, (err, buf) => {
        if (err) {
          return reject(err);
        }
        const filename = buf.toString('hex') + path.extname(file.originalname);
        const fileInfo = {
          filename: filename,
          bucketName: 'uploads'
        };
        resolve(fileInfo);
      });
    });
  }
});
const upload = multer({ storage });

module.exports = {
  upload,
  initGfs,
  conn
}

2. 修正路由文件

通过async/await等待GFS初始化完成,并修正导入方式:

const { initGfs } = require('../models/mongoose');

exports.getImg = async (req, res) => {
  try {
    // 等待GFS初始化完成
    const { gfs, gridfsBucket } = await initGfs;
    console.log(`req file name is: ${req.params.filename}`);
    
    const file = await gfs.files.findOne({ filename: req.params.filename });

    // 检查文件是否存在
    if (!file) {
      return res.status(404).json({ err: "文件不存在" });
    }

    // 检查是否为图片类型
    const allowedTypes = ["image/jpeg", "image/png", "image/jpg", "image/heic"];
    if (allowedTypes.includes(file.contentType)) {
      const readstream = gridfsBucket.openDownloadStreamByName(file.filename);
      readstream.pipe(res);
    } else {
      res.status(404).json({ err: "不是图片文件" });
    }
  } catch (err) {
    console.error(err);
    res.status(500).json({ err: "服务器内部错误" });
  }
};

内容的提问来源于stack exchange,提问作者Dor Dadon

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.11 05:55:20