使用Node.js,Express.js和gridfs-stream直接将文件stream式传输到GridFS

我使用的是最新版本的express,mongodb,nodejs等。我没有使用正文parsing中间件,因为我不想在磁盘上传文件时将文件存储。 我只是想将它们直接stream入GridF。 我正在使用gridfs-stream npm模块。 我知道ExpressJs在底下使用强大。 请记住 – 我不希望文件打到磁盘。

这里是我的路由处理程序,我只是发布一个多部分表单 – 表单包含一个文件,只有1-3可选字段。

为什么哦为什么form.on('部分',函数(部分)) – 多次调用文件的相同部分超过100kb,而对于较小的文件 – 我们只是得到一个调用?

我真正想要做的是实际上将一个文件从一个上传文件直接传输到GridF中,并将同一文章中的所有表单文章域添加到GridFs元数据中。

mymodule.prototype.save = function(req,res,next) { if(req._body) { //return next(); }else if(contentType(req) !== 'multipart/form-data') { return next(); } var gfs = Grid(req.ctx.app.database.connection.db, mongo); req.body || (req.body = {}); req.files || (req.files = {}); var form = req.form, body = req.body, files = req.files, cb_called = false; var parts = {}; var info = ''; var fileId = mongoose.Types.ObjectId(); var gfs_ws; form.on('part', function(part) { if (part.filename) { ///// THIS IS CALLED MORE THAN ONCE for each part.filename???? on large files -- but why??? sendPart(part); } }); form.on('field', function(name, value) { if ( Array.isArray(body[name]) ) { body[name].push(value); }else if (body[name]) { body[name] = [body[name], value]; }else{ body[name] = value; } }); form.on('error', function(err) { if (err && err.length > 1){ res.statusCode = 200; res.send({success: false, err: err}); } }); form.on('close', function() { try { //req.body = qs.parse(body); // if additional fields sent - for now we ignore them } catch (err) { return next(err); } res.send({ success: true }); //, id: fileId.toString() }); }); form.parse(req); function contentType(req) { return req.headers['content-type'] && req.headers['content-type'].split(';')[0]; } function sendPart(part) { if (!gfs_ws) { // THIS IS MY ATTEMPT TO STREAM ALL PARTS OF THE SAME FILE TO THE SAME GRIDFS RECORD - but really we should only ever have called sendPart(part) once for each file var options = { _id: fileId, // a MongoDb ObjectId filename: part.filename, // a filename mode: 'w', // default value: w+, possible options: w, w+ or r, see [GridStore](http://mongodb.github.com/node-mongodb-native/api-generated/gridstore.html) //any other options from the GridStore may be passed too, eg: //chunkSize: 1024, content_type: part.headers['content-type'], //file.type , // For content_type to work properly, set "mode"-option to "w" too! //root: 'my_collection', metadata: { recordId: req.params.recordid, elementId: req.params.elementid } }; gfs_ws = gfs.createWriteStream(options); } part.pipe(gfs_ws); } 

}

当我发布小文件(即<100kb)form.on('part'…每个文件部分只调用一次 – 每个字段部分只调用一次,我只在文件中有文件 – 所以sendPart(part)只有被称为一个和文件被放在GridFs和快乐的日子。

然而 – 大文件,即> 100kb – form.on('part' – 多次调用同一个文件 – 即part.filename是

您可能不希望为了执行此操作而设置正文parsing器。 您实际上需要直接使用pipe接口。

有两件事,首先在body parser中configurationexpress来mutipart函数。 在这篇文章中描述:

如何禁用用于file upload的Express BodyParser(Node.js)

其次,使用pipe道来引导网格stream ,作为另一个组件。 这篇文章给出了一个示例用法:

在GridFS,express,mongoDB,node.js中存储来自POST请求的数据stream