Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

busboy not firing finish event

I am trying to pass a request object from my routes to a controller which processes the uploads,

here is the route -

app.post('/upload/notes',auth.requiresApiLogin,function(req,res){
        upload.file(req,res);
});

here is the controller (upload.js) code which has the exported file method

var fs = require('fs'),
    uuid = require('node-uuid'),
    path = require('path'),
    Busboy = require('busboy');
exports.file = function(req, res) {
    var busboy = new Busboy({ headers: req.headers});
    busboy.on('file', function(fieldname, file, filename,transferEncoding,mimeType) {
        console.log("inside upload function");
        console.log(file);
    });
    busboy.on('field', function(fieldname, val, valTruncated,keyTruncated) {
        console.log("inside field function");
        console.log(fieldname);
    });
    busboy.on('finish',function(){
        console.log('finished');
    });
    req.pipe(busboy);
//
//    req.pipe(req.busboy);
//    req.busboy.on('file', function(fieldname, file, filename,transferEncoding,mimeType) {
//        var fName = uuid.v4();
//        console.log(filename);
//        var fileext = filename.substr(filename.lastIndexOf('.') + 1);
//
//        console.log(transferEncoding);
//        console.log(mimeType);
//        var filepath = path.normalize(__dirname + '/../../');
//        var fstream = fs.createWriteStream(filepath+'/server/uploads/'+fName+'.'+fileext);
//        file.pipe(fstream);
//        fstream.on('close', function () {
//            res.redirect('back');
//        });
//    });
};

So, what i see that both the fields and the files are being logged in console but the finish event is not getting fired. What else should i try ?

like image 748
Harshit Laddha Avatar asked Jul 05 '14 16:07

Harshit Laddha


2 Answers

You need to consume the file stream somehow. For testing purposes you can ignore the data by adding file.resume(); inside the file event handler.

like image 146
mscdex Avatar answered Oct 19 '22 11:10

mscdex


This answer might help someone who wants to consume the file...

Make sure to pass control back to express by calling next() in the finish method after consuming the file e.g.

app.use(function(req: Request, res: ServerResponse, next:any) {
let bb = new busboy({ headers: req.headers });
let fileData: any = null;
const fieldArray: any = [];
let dataLength: number;
const extractFields =  (name: string, val: any, data: any) => {
  if (Array.isArray(data[name])) {
    data[name].push(val);
  } else if (data[name]) {
    data[name] = [data[name], val];
  } else {
    data[name] = val;
  }
};
bb.on('field', function(fieldname: string, val:any, fieldnameTruncated: boolean, valTruncated: boolean, encoding: string, mimetype: string) {
  // extract fields to add to req body for later processing
  extractFields(fieldname, val, fieldArray);
  console.log('Field [' + fieldname + ']: value: ' + val);

});

bb.on('file', function(fieldname: string, file: NodeJS.ReadableStream , filename: string, encoding: string, mimetype: string) {
  file.on('data', function(data) {
    console.log('File [' + fieldname + '] got ' + data.length + ' bytes');
    // Process buffer to save complete file to add to the req for access later
    if (fileData === null) {
      fileData = data;
    } else {
      fileData = Buffer.concat([fileData, data]);
    }
  });
  file.on('end', function() {
    console.log('File [' + fieldname + '] Finished');
  });
});

bb.on('finish', function() {
  req.body = fieldArray
  req.body.files = {file: fileData};
  console.log('Done parsing form!');
  next(); // <- Allows processing to continue and avoids request hanging
});

bb.on('close', () => {
console.log('Event closed')
});
// what does this do? Send the readable request stream to busboy which is a writeable stream. The above code dictates to the writeable
// how to respond when certain events are fired during the pipe.
req.pipe(bb);
});
like image 24
Norbert Avatar answered Oct 19 '22 10:10

Norbert