经过进一步研究,我发现原生“http”模块确实支持我提到的流式传输。我不确定快递是否支持这一点。我猜是这样,但在上传的情况下,您可能无法使用 bodyParser 中间件,因为它可能会阻塞,直到收到整个请求正文。
无论如何,这里有一些代码展示了如何将传入请求流式传输到 MongoDB 的 GridFS:
var http = require('http');
var mongo = require('mongodb');
var db = new mongo.Db('somedb', new mongo.Server("localhost", 27017), { safe: true });
db.open(function(err) {
if (err)
console.log(err);
http.createServer(function(req, res) {
var numToSave = 0;
var endCalled = false;
new mongo.GridStore(db, new mongo.ObjectID(), "w", { root: "fs", filename: "test" }).open(function(err, gridStore) {
if(err)
console.log(err);
gridStore.chunkSize = 1024 * 256;
req.on("data", function(chunk) {
numToSave++;
gridStore.write(chunk, function(err, gridStore) {
if(err)
console.log(err);
numToSave--;
if(numToSave === 0 && endCalled)
finishUp(gridStore, res);
});
});
req.on("end", function() {
endCalled = true;
console.log("end called");
if(numToSave === 0)
finishUp(gridStore, res);
});
});
}).listen(8000);
});
function finishUp(gridStore, res) {
gridStore.close();
res.end();
console.log("finishing up");
}
要点是 req 对象实际上是一个带有“数据”和“结束”事件的流。每次发生“数据”事件时,您都会将一大块数据写入 mongo。当“结束”事件发生时,您关闭 mongo 连接并发送响应。
协调所有不同的异步活动有些令人讨厌。在您有机会实际写出所有数据之前,您不想关闭 mongo 连接。我通过计数器和布尔值实现了这一点,但使用某些库可能会有更好的方法。