【问题标题】:Error: The database connection must be open to store files at GridFSStorage._handleFile错误:必须打开数据库连接才能将文件存储在 GridFSStorage._handleFile
【发布时间】:2020-09-15 19:51:18
【问题描述】:

我想用 multer 使用 nodejs/angular 应用程序添加文件。相同的代码(nodejs 部分)在 nodejs/react-redux 应用程序上运行良好。

这是 server.js 代码(其中最重要的是消息路由):

const express = require('express'); 
const cors = require('cors'); 
const path = require('path'); 
const mongoose = require('mongoose'); 
require('dotenv').config(); 
require('./modules/auth');
const passport = require('passport');
const cookieSession = require('cookie-session');
const bodyParser = require('body-parser');
// #6 Initialize an Express application 
const app = express();

// Bodyparser MiddlewareFirst way
app.use(bodyParser.urlencoded({limit: '50mb', extended: false}));
app.use(bodyParser.json({limit: '50mb', extended: false}));

// Bodyparser Middleware - second way
app.use(express.json());
app.use(cors()); 


app.use(cookieSession({
  name: 'session',
  keys: ['key1', 'key2']
}))

app.use(passport.initialize());
app.use(passport.session());

const db = process.env.mongoURI;

// Connect to Mongo
mongoose 
  .connect(db, { 
    useNewUrlParser: true,
    useCreateIndex: true, 
    useUnifiedTopology: true, 
    useFindAndModify: false }) // Adding new mongo url parser 
  .then(() => console.log('MongoDB Connected...')) 
  .catch(err => console.log(err)); 

app.use('/api/messages', require('./routes/api/messages'));
app.use('/api/posts', require('./routes/api/posts'));
app.use('/auth', require('./routes/auth'));


app.use(express.static(path.join(__dirname, 'dist')));

app.get('*', (req, res) => { 
    res.sendFile(path.join(__dirname, 'dist/index.html')) 
}); 
const PORT = process.env.PORT || 4000; 
app.listen(PORT, () => console.log(`Server started on port ${PORT}`));

我还尝试删除/注释所有内容,例如模块/身份验证、所有护照部分代码和其他路由,但它仍然不起作用。(当 console.log 连接时,我看到只有用户模型/架构/集合包括,即使我有三个模型(和三个路由)。所以我也尝试使用身份验证路由添加文件,但它也不起作用。

所以现在我将显示我的消息路由(当我不添加任何文件时,它可以正常工作,因此必须打开连接)。

routes/api/messages.js

const router = require('express').Router();
const mongoose = require('mongoose');
const Grid = require('gridfs-stream');
const { initStorage, initUpload } = require('../../modules/multerModule');

const conn = mongoose.connection;
Grid.mongo = mongoose.mongo;

// console.log(conn);
// Init gfs
let gfs;

conn.once('open', () => {
  // Init stream
  gfs = Grid(conn.db);
  gfs.collection(collectionName);
});

const collectionName = 'messages';
const bucketName = 'messages';

console.log(conn);

const storage = initStorage(conn, bucketName);

const upload = initUpload(storage);


// File Model
const Message = require('../../models/message');

// @route GET /
// @desc Loads form
router.get('/', (req, res) => {
  Message.find()
    .sort({ date: 1 })
    .then(messages => res.json(messages))
});


// @route POST /upload
// @desc  Uploads file and object to DB
router.post('/', upload.single('message'), (req, res) => {

  const fileImage = (req.body.fileImage == 'true');
  console.log(fileImage);
  if (req.files !== undefined) {
    const { files } = req;
    const { id, filename } = files[0];
    const newMessage = new Message({
      files_id: id,
      fileImage: req.body.fileImage,
      path: '/api/messages/image/' + filename,
      content: req.body.content
      // Grab the file id that was stored in the database by the storage engine as the messages to your file
    })
    newMessage.save().then(messages => res.json(messages));
  }
  else {
    const newMessage = new Message({
      files_id: mongoose.Types.ObjectId(),
      path: req.body.path,
      fileImage: req.body.fileImage,
      content: req.body.content
      // Grab the file id that was stored in the database by the storage engine as the messages to your file
    })
    newMessage.save().then(messages => res.json(messages));
  }
});

// ... here's also put and gets filename routes, but that's not important right now

module.exports = router;

还有我的存储功能:

模块/multerModule.js

const path = require('path');
const multer = require('multer');
const crypto = require('crypto');
const GridFsStorage = require('multer-gridfs-storage');

// Create storage engine
const initStorage = (conn, bucketName) => new GridFsStorage({
  db: conn,
  file: (req, file) => {
    return new Promise((resolve, reject) => {
      crypto.randomBytes(16, (err, buf) => {
        if (err) {
          return reject(err);
        }
        const filename = buf.toString('hex') + path.extname(file.originalname);
        const fileInfo = {
          filename: filename,
          bucketName: bucketName
        };
        resolve(fileInfo);
      });
    });
  }
});

// Create upload module
const initUpload = (storage) => multer({
  storage: storage,
  fileFilter: function (req, file, callback) {
    const ext = path.extname(file.originalname);
    if (ext !== '.png' && ext !== '.jpg' && ext !== '.gif' && ext !== '.jpeg') {
      return callback(new Error('Only images are allowed'))
    }
    callback(null, true)
  }
});

module.exports = { initStorage, initUpload };

我已经尝试了所有方法,如果您知道为什么它不起作用,请与我分享。

这是我的连接数据的一些截图:

我对代码进行了一次更改并得到了新的错误,但它正在向前发展:

我在使用之前已经导入了路线:

const messages = require('./routes/api/messages');
const posts = require('./routes/api/posts');
const auth = require('./routes/auth');

//...

app.use('/api/messages', messages);
app.use('/api/posts', posts);
app.use('/auth', auth);

我得到这个错误:

TypeError: Cannot read property 'isConnected' of undefined

导致initStorage函数:

const conn = mongoose.connection;
Grid.mongo = mongoose.mongo;

// console.log(conn);
// Init gfs
let gfs;

conn.once('open', () => {
  // Init stream
  gfs = Grid(conn.db);
  gfs.collection(collectionName);
});

const collectionName = 'messages';
const bucketName = 'messages';

console.log(conn);

const storage = initStorage(conn, bucketName); // here comes the error, but it can be connected with conn variable.

还有initStorage函数(我会再展示一遍):

const path = require('path');
const multer = require('multer');
const crypto = require('crypto');
const GridFsStorage = require('multer-gridfs-storage');

// Create storage engine
const initStorage = (conn, bucketName) => new GridFsStorage({
  db: conn,
  file: (req, file) => {
    return new Promise((resolve, reject) => {
      crypto.randomBytes(16, (err, buf) => {
        if (err) {
          return reject(err);
        }
        const filename = buf.toString('hex') + path.extname(file.originalname);
        const fileInfo = {
          filename: filename,
          bucketName: bucketName
        };
        resolve(fileInfo);
      });
    });
  }
});

【问题讨论】:

    标签: javascript node.js mongoose multer gridfs


    【解决方案1】:

    好的,我找到了答案,但是我不知道为什么猫鼬连接中的某些东西被破坏了:

    在 initStorage 中,我只是直接完成了它,并且它运行良好:

    // Create storage engine
    const initStorage = (url, bucketName) => new GridFsStorage({
      url: url,
      file: (req, file) => {
        return new Promise((resolve, reject) => {
          crypto.randomBytes(16, (err, buf) => {
            if (err) {
              return reject(err);
            }
            const filename = buf.toString('hex') + path.extname(file.originalname);
            const fileInfo = {
              filename: filename,
              bucketName: bucketName
            };
            resolve(fileInfo);
          });
        });
      }
    });
    

    所以我的问题是,为什么 server.js 中的这个猫鼬连接断开了?

    【讨论】:

      猜你喜欢
      • 2019-05-29
      • 2020-01-30
      • 1970-01-01
      • 2011-05-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多