2012-07-02 26 views
57

Điều này có vẻ như nó phải là một câu hỏi khá đơn giản, nhưng tôi đang có một thời gian thực sự khó khăn để tìm ra cách tiếp cận nó.Cách tắt Express BodyParser để tải lên tệp (Node.js)

Tôi đang sử dụng Node.js + Express để xây dựng ứng dụng web và tôi tìm thấy trình kết nối BodyParser thể hiện rất hữu ích trong hầu hết các trường hợp. Tuy nhiên, tôi muốn có quyền truy cập chi tiết hơn để đa POSTS dữ liệu biểu mẫu khi chúng đến - tôi cần dẫn luồng đầu vào đến máy chủ khác và muốn tránh tải xuống toàn bộ tệp trước.

Vì tôi đang sử dụng Express BodyParser, tuy nhiên, tất cả các tệp tải lên được phân tích cú pháp tự động và tải lên và có sẵn bằng cách sử dụng "request.files" trước khi chúng có được bất kỳ chức năng nào của tôi.

Có cách nào để tắt BodyParser cho các bài đăng dạng nhiều biểu mẫu mà không tắt nó cho mọi thứ khác không?

+1

Aaaarg! Tôi đã dành hơn một ngày cố gắng tìm ra lý do tại sao tôi không thể tải lên các tập tin khi các ứng dụng mẫu (không có Express, nhưng cũng rõ ràng, với nhiều sự khác biệt khác quá) làm việc hoàn hảo. Hóa ra 'bodyParser' là thủ phạm. Cảm ơn bạn đã hỏi điều này. – meloncholy

Trả lời

16

Whe n bạn nhập app.use(express.bodyParser()), gần như mỗi yêu cầu sẽ trải qua các chức năng bodyParser (cái nào sẽ được thực hiện tùy thuộc vào tiêu đề Content-Type).

Theo mặc định, có 3 tiêu đề được hỗ trợ (AFAIR). Bạn có thể thấy các nguồn để chắc chắn. Bạn có thể (lại) xác định xử lý cho Content-Type s với một cái gì đó như thế này:

var express = require('express'); 
var bodyParser = express.bodyParser; 

// redefine handler for Content-Type: multipart/form-data 
bodyParser.parse('multipart/form-data') = function(req, options, next) { 
    // parse request body your way; example of such action: 
    // https://github.com/senchalabs/connect/blob/master/lib/middleware/multipart.js 

    // for your needs it will probably be this: 
    next(); 
} 


UPD.

Mọi thứ đã thay đổi trong tốc 3, vì vậy tôi chia sẻ đang được cập nhật từ dự án làm việc (nên app.use ed trướcexpress.bodyParser()):

var connectUtils = require('express/node_modules/connect/lib/utils'); 

/** 
* Parses body and puts it to `request.rawBody`. 
* @param {Array|String} contentTypes Value(s) of Content-Type header for which 
             parser will be applied. 
* @return {Function}     Express Middleware 
*/ 
module.exports = function(contentTypes) { 
    contentTypes = Array.isArray(contentTypes) ? contentTypes 
              : [contentTypes]; 
    return function (req, res, next) { 
    if (req._body) 
     return next(); 

    req.body = req.body || {}; 

    if (!connectUtils.hasBody(req)) 
     return next(); 

    if (-1 === contentTypes.indexOf(req.header('content-type'))) 
     return next(); 

    req.setEncoding('utf8'); // Reconsider this line! 
    req._body = true;  // Mark as parsed for other body parsers. 
    req.rawBody = ''; 

    req.on('data', function (chunk) { 
     req.rawBody += chunk; 
    }); 

    req.on('end', next); 
    }; 
}; 

Và một số mã giả, liên quan đến câu hỏi ban đầu:

function disableParserForContentType(req, res, next) { 
    if (req.contentType in options.contentTypes) { 
    req._body = true; 
    next(); 
    } 
} 
+0

Hoặc bạn có thể 'xóa express.bodyParser.parse ['multipart/form-data'];' ** trước ** 'app.use (express.bodyParser())' như @jwerre – elmigranto

61

Nếu bạn cần sử dụng chức năng được cung cấp bởi express.bodyParser nhưng bạn muốn tắt tính năng này cho nhiều phần/biểu mẫu dữ liệu, mẹo không được sử dụng express.bodyParser directly. express.bodyParser là phương pháp tiện lợi bao gồm ba phương pháp khác: express.json, express.urlencodedexpress.multipart.

Vì vậy, thay vì nói

app.use(express.bodyParser()) 

bạn chỉ cần nói

app.use(express.json()) 
    .use(express.urlencoded()) 

này cung cấp cho bạn tất cả những lợi ích của bodyparser cho hầu hết các dữ liệu trong khi cho phép bạn xử lý ảnh upload formdata một cách độc lập.

Chỉnh sửa:jsonurlencoded hiện không còn được bao gồm với Express. Họ được cung cấp bởi các module riêng biệt body-parser và bây giờ bạn sử dụng chúng như sau:

bodyParser = require("body-parser") 
app.use(bodyParser.json()) 
    .use(bodyParser.urlencoded()) 
+15

Hoặc bạn có thể định nghĩa 'bodyParser' của riêng bạn cho tiêu đề kiểu nội dung' multipart/form-data': 'require ('express'). BodyParser.parse ['multipart/form-data'] = function yourHandler (req, options , tiếp theo) ... ' – elmigranto

+0

Thậm chí còn tốt hơn - nếu bạn gửi câu trả lời đó bằng một mẫu mã ngắn, tôi sẽ làm cho nó là câu trả lời được chấp nhận cho chuỗi. Điều đáng chú ý là tìm kiếm thông tin đơn giản như thế nào. Cảm ơn! – Myk

+0

Điều này thực sự hữu ích để biết, đặc biệt là để làm mỏng đi sự phụ thuộc của các ứng dụng được gắn kết! – wprl

27

Nếu nhu cầu về phân tích cơ thể chỉ phụ thuộc vào con đường riêng của mình, điều đơn giản nhất là sử dụng bodyParser là một hàm tuyến đường trung chỉ trên các tuyến đường cần nó hơn là sử dụng nó App-rộng:

var express=require('express'); 
var app=express.createServer(); 
app.post('/body', express.bodyParser(), function(req, res) { 
    res.send(typeof(req.body), {'Content-Type': 'text/plain'}); 
}); 
app.post('/nobody', function(req, res) { 
    res.send(typeof(req.body), {'Content-Type': 'text/plain'}); 
}); 
app.listen(2484); 
+1

Câu trả lời xuất sắc. – antonio081014

1

ném đây là trước khi app.configure

delete express.bodyParser.parse['multipart/form-data']; 
+0

Tôi đã thử rằng ở các phần khác nhau trong mã của tôi và nó luôn làm hỏng ứng dụng ngay lập tức. – Myk

+0

Bạn đã đặt nó trước khi bạn khởi tạo bodyParser của bạn? Nếu không, bạn nên làm điều đó. – jwerre

+0

nó cũng treo cho tôi: ( – nick

15

trong Express 3, bạn có thể vượt qua tham số cho bodyParser như {defer: true} - mà trong nhiệm kỳ trì hoãn đa xử lý một phần và trưng ra đối tượng Formidable như req.form. Có nghĩa là mã của bạn có thể là:

... 
app.use(express.bodyParser({defer: true})); 

... 
// your upload handling request 
app.post('/upload', function(req, res)) { 
    var incomingForm = req.form // it is Formidable form object 

    incomingForm.on('error', function(err){ 

      console.log(error); //handle the error 

    }) 

    incomingForm.on('fileBegin', function(name, file){ 

     // do your things here when upload starts 
    }) 


    incomingForm.on('end', function(){ 

     // do stuff after file upload 
    }); 

    // Main entry for parsing the files 
    // needed to start Formidables activity 
    incomingForm.parse(req, function(err, fields, files){ 


    }) 
} 

Đối với chi tiết xử lý sự kiện đáng gờm tham khảo https://github.com/felixge/node-formidable

+0

Tôi không chắc liệu mình có làm gì sai hay không, nhưng người nghe sự kiện sẽ không làm việc trong trường hợp của tôi.Tôi đã kiểm tra mã nguồn của multipart.js và phần mềm trung gian gọi sau khi phân tích toàn bộ dữ liệu (và không có khả năng gọi nó hai lần), do đó, sự kiện được phát ra trước khi chuyển nhượng trong ví dụ của bạn – JakubKnejzlik

+2

Có vẻ như Formidable không còn được bao gồm trong Express 4. Xem https://github.com/felixge/node-formidable/issues/264 –

4

tôi đã phải đối mặt với vấn đề tương tự trong 3.1.1 và tìm thấy (không quá khá IMO) giải pháp:

để vô hiệu hóa bodyParser cho multipart/form-data:

var bodyParser = express.bodyParser(); 
app.use(function(req,res,next){ 
    if(req.get('content-type').indexOf('multipart/form-data') === 0)return next(); 
    bodyParser(req,res,next); 
}); 

và phân tích các nội dung:

app.all('/:token?/:collection',function(req,res,next){ 
    if(req.get('content-type').indexOf('multipart/form-data') !== 0)return next(); 
    if(req.method != 'POST' && req.method != 'PUT')return next(); 
    //...use your custom code here 
}); 

ví dụ tôi đang sử dụng nút-đa đảng nơi mã tùy chỉnh sẽ giống như thế này:

var form = new multiparty.Form(); 

    form.on('file',function(name,file){ 
     //...per file event handling 
    });  

    form.parse(req, function(err, fields, files) { 
     //...next(); 
    }); 
Các vấn đề liên quan