问题在于您不只是将文件请求传送到 gridfs-stream。使用 Multer 作为中间件并捕获任何multipart/form-data
发布请求。当数据流进入时,Multer(基于Busboy) 监视on('field')
and on('file')
事件并进行相应的解析。您通过管道传送给 Multer 的不仅仅是一个文件。
这段代码工作正常,因为 Multer 确实已经为你解析出来了req.files
and req.body
至此:
// Create a gridfs-stream
var gfs = new Gridfs(db, mongoDriver);
var file = req.files.myFile;
var fileId = new ObjectId();
console.log("Creating WriteStream");
var writeStream = gfs.createWriteStream({
_id: fileId,
filename: file.originalname,
mode: 'w',
content_type: file.mimetype,
metadata: {
id: '123',
number: '2',
name: "Kenny Erasmuson"
}
});
console.log("Created WriteStream");
但是由于上述原因,您的代码遇到问题的地方在这里:
req.pipe(writeStream);
我还没有找到一种方法来传输多部分/表单数据发布请求,而不仅仅是直接将文件上传到 GridFS。如果您的 post 请求不包含文件以外的任何内容(意味着表单中没有其他 html 输入字段),那么您可能需要考虑至少针对此路由从中间件中删除 Multer。
对于我的用例,我需要能够接收带有文本输入的 html 表单帖子以及文件上传(我存储有关上传文件的元数据)。以下是我如何使用 Multer 完成我所需要的工作:
var uploadImg = function(req,res) {
var writestream = gfs.createWriteStream({
filename: req.files.file.name,
mode:'w',
content_type:req.files.file.mimetype,
metadata:req.body,
});
fs.createReadStream(req.files.file.path).pipe(writestream);
writestream.on('close', function (file) {
res.send("Success!");
fs.unlink(req.files.file.path, function (err) {
if (err) console.error("Error: " + err);
console.log('successfully deleted : '+ req.files.file.path );
});
});
};
默认情况下,Multer 会将您的文件存储在磁盘上。一种快速解决方案是创建一个读取流并将其直接流回 GridFS。写入完成后,删除tmp文件。
附带说明一下,似乎有人认为最好仅在需要它的路由上使用 Multer 作为中间件。您可以在最后一节中阅读有关该想法的更多信息this.
Update
我想我即将找到一种直接流式传输到 GridFS 的方法with元数据通过使用Skipper。我正在查看是否无法获取某些更新船长 gridfs这将获取 html 表单上的文本输入并将其设置为元数据等。对船长-gridfs 的调整似乎很小。当它被冲掉时我会更新。如果您查看船长,请确保您认识到 html 表单输入的顺序(如果有的话)确实很重要。