2014-02-23 48 views
2

我正在使用express,mongodb,nodejs等的最新版本。我不使用body解析中間件,因爲我不想將文件存儲在磁盤上我上傳他們。我只是想直接將它們流入GridF。我正在使用gridfs-stream npm模塊。我知道ExpressJs在底下使用強大。請記住 - 我不希望文件打到磁盤。使用Node.js,Express.js和gridfs-stream直接將文件流式傳輸到GridFS中

這裏是我的路由處理程序,我只是發佈一個多部分表單 - 表單只包含一個文件以及1-3個可選字段。

爲什麼哦爲什麼form.on('part',function(part)) - 多次調用文件的同一部分超過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, e.g.: 
      //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(「部分」 ......被稱爲只是一次爲每個文件的一部分。只有文件中的文件 - 所以sendPart(部分)只被稱爲一個,文件獲取放在GridFs和快樂的日子。

然而 - 與更大的文件,即> 100kb - form.on('部分' - 被調用多次爲同一個文件 - 即part.filename是

回答

0

你可能不希望爲了執行此操作而設置正文解析器。您實際上需要直接使用接口pipe

有兩件事,首先配置表達式以在主體解析器中diable mutipart函數。描述在這篇文章:

How to disable Express BodyParser for file uploads (Node.js)

其次使用管道到信道到gridfs-stream,作爲另一組分。這篇文章給出了一個實例:

Storing data stream from POST request in GridFS, express, mongoDB, node.js

+0

喜尼爾 - 感謝您的答覆。我有這樣的東西安裝: app.use(express.json()); app.use(express.urlencoded()); (express.multipart({defer:true})); 我以前遇到發佈的兩個鏈接。這兩個問題都沒有涉及到底層的問題,這就是爲什麼form.on('同一部分的多次部分火災?我應該期望它嗎?如果是這樣,我將如何緩衝輸入數據,然後將該緩衝區變成管道? – user2081478

相關問題