我在尝试动态地更新导出的Multer GridFS模块中的metadata
属性时遇到了一些困难。该模块包含一个“上传引擎”,用于处理将文件上传到我的数据库。这是multer-gridfs-storage
库。
这是我的GridFs上传模块gridFs_upload_engine.js
:
> //Upload Engine const mongoose = require('mongoose'); const path =
> require('path'); const crypto = require('crypto'); const multer =
> require('multer'); const GridFsStorage =
> require('multer-gridfs-storage'); const Grid =
> require('gridfs-stream');
>
> //Init Upload Engine let gfs; const database = mongoose.connection;
> const mongoDb = process.env.MONGODB_URI || process.env.MLAB_URL;
>
> database.once('open', () => { //Init Stream gfs =
> Grid(database.db, mongoose.mongo); gfs.collection('uploads'); });
>
> //Create Storage Engine const storage = new GridFsStorage({ url:
> mongoDb, 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: 'uploads',
> metadata: 'Add Metadata here'
> };
> resolve(fileInfo);
> });
> }); } });
>
> const uploadEngine = multer({ storage });
>
> module.exports = { engine: uploadEngine, gfs };
我需要更改上面的metadata
属性。 fileinfo
会将此GridFs
对象在上载时添加到每个文件中。我以为req
参数可以访问调用此中间件的路由的req.body
,但它以undefined
的形式返回。
这是我的考试路线:
const express = require('express');
const router = express.Router();
//Controllers
const upload_controller = require('../../controllers/uploader');
//Dependencies
const upload = require('../../utils/gridFs_upload_engine');
const { engine } = upload;
//Upload Single File
router.post(
'/single',
engine.single('file'),
upload_controller.upload_single_file
);
在这里,我将GridFs
中间件传递到我的API路由中。这样,控制器就可以利用它。
这是我的upload controller
:
exports.upload_single_file = (req, res, next) => {
console.log({ file: req.file });
res.redirect('/');
};
console.log
注销按预期使用GridFs
上传引擎上传的文件的信息。
我知道我需要以某种方式将参数传递给gridFs_upload_engine.js
。由于此文件是导出的模块,因此我不确定如何完成此操作。我可以将这段代码直接放入API控制器中,然后以这种方式进行处理,但是我希望它是一个可以从其他控制器调用的模块。
答案 0 :(得分:0)
最后,我通过公开一个让我更新变量的函数解决了这个问题,该变量然后用作metadata
值。
API路线:
//Dependencies
const upload = require('../../utils/gridFs_upload_engine');
const { engine, updateMetadata } = upload;
//Upload Single File
router.post(
'/single',
(req, res, next) => {
updateMetadata('xxxxxx'); //Static test value
next();
},
engine.single('file'),
upload_controller.upload_single_file
);
在这里,我添加了一个回调,其中包含上载引擎公开的updateMetadata()
函数。在这里,我使用公开的metadata
函数设置updateMetadata()
。之后,通过使用next()
,router
移至engine.single('file')
上,这实际上是处理文件上传的方法。
这是GridFs
上传引擎:
//Create Storage Engine
let updatedMetadata;
const updateMetadata = id => {
updatedMetadata = id;
};
const storage = new GridFsStorage({
url: mongoDb,
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: 'uploads',
metadata: updatedMetadata ? updatedMetadata : null
};
resolve(fileInfo);
});
});
}
});
const uploadEngine = multer({ storage });
module.exports = {
engine: uploadEngine,
updateMetadata,
gfs
};
我不确定这是否是执行此操作的最佳方法,但是它可以正常运行且符合预期,因此我将不再对此提出任何疑问。希望这对某人有帮助!
答案 1 :(得分:0)
上述解决方案不适用于Google搜索了一堆cant access req.body inside metadata. · Issue #1 · devconcept/multer-gridfs-storage
感到很傻,我在创建存储引擎时无法访问req之前就没有看到它
const storage = new GridFsStorage({
url: db,
options: { useNewUrlParser: true, useUnifiedTopology: true },
file: (req, file) => {
return new Promise((resolve, reject) => {
crypto.randomBytes(16, (err, buf) => {
if (err) {
return reject(err);
}
let metaData;
if(req.body && req.body.checked){
metaData = true
}
const filename = buf.toString("hex") + path.extname(file.originalname);
const fileInfo = {
filename: filename,
bucketName: "uploads",
metadata: metaData ? metaData : null
};
resolve(fileInfo);
});
});
}
});