Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

busboy - is there a way to send the response when all files have been uploaded?

Tags:

node.js

busboy

I'm trying to upload files to a server using node.js as backend and angular.js as frontend. I'm using express 4 + busboy for this. I have a table in the frontend where I should display all the files I'm uploading. So if I have 3 files and click on upload, angular should post these files to node.js and after getting the response back, refresh the table with those three files. This is the function I'm using in angular:

function uploadFiles(files){
    var fd = new FormData();
    for(var i = 0; i<files.length; i++){
        fd.append("file", files[i]);
    }
    $http.post('http://localhost:3000/upload', fd, {
        withCredentials: false,
        headers: {'Content-Type': undefined },
        transformRequest: angular.identity
    }).success(refreshTable()).error(function(){
        console.log("error uploading");
    });
}

and this is from node.js:

app.post('/upload', function(req, res) {
  var busboy = new Busboy({ headers: req.headers });
  busboy.on('file', function (fieldname, file, filename) {
    console.log("Uploading: " + filename);
    var fstream = fs.createWriteStream('./files/' + filename);
    file.pipe(fstream);
  });
  busboy.on('finish', function(){
    res.writeHead(200, { 'Connection': 'close' });
    res.end("");
  });
  return req.pipe(busboy);
});

the problem is that if I upload three files, as soon as the first file has been uploaded node.js sends the response and hence the table is updated only with the first file uploaded, if I refresh the page, the rest of the files appear. I think the problem is with this line in node: return req.pipe(busboy); if I remove that line, the post response keeps on pending for a long time and nothing happens, I think this is an async problem, anybody knows if there's a way to send the response back only when all files have been uploaded? thanks

like image 357
nelson687 Avatar asked May 01 '15 23:05

nelson687


People also ask

How to upload NodeJS file upload with Busboy?

Nodejs file upload with busboy 1 Step 1 – Export Dependencies. 2 Step 2 – Creating Form. To upload file we need a form. We will create form with `file input` element that allows to us... 3 Step 3 – Handle Form Submit. Here we will handle the form, We will parse the form and store the file in the folder. To... More ...

How does busboy handle file parameters?

The method accepts 2 parameters: Whenever busboy parses parameter of type file we check for the data value and if it’s not null we concatenate it in into the existing fileData buffer variable. This is done for files that are too big to get parsed all at once.

Can We still use Express and still use middleware connect-busboy?

More specifically we will use middleware connect-busboy so we can still use Express. All code is commented and should be quite self-explanatory. Let’s start up the server and upload ~1.2GB file. From “simple” monitoring of the resources we can see that memory consumption is not significantly increased when handling this large file.


1 Answers

A simple and common solution to this particular problem is to use a counter variable and listening for the finish event on the fs Writable stream. For example:

app.post('/upload', function(req, res) {
  var busboy = new Busboy({ headers: req.headers });
  var files = 0, finished = false;
  busboy.on('file', function (fieldname, file, filename) {
    console.log("Uploading: " + filename);
    ++files;
    var fstream = fs.createWriteStream('./files/' + filename);
    fstream.on('finish', function() {
      if (--files === 0 && finished) {
        res.writeHead(200, { 'Connection': 'close' });
        res.end("");
      }
    });
    file.pipe(fstream);
  });
  busboy.on('finish', function() {
    finished = true;
  });
  return req.pipe(busboy);
});

The reason for this is that busboy's finish event is emitted once the entire request has been fully processed, that includes files. However, there is some delay between when there is no more data to write to a particular file and when the OS/node has flushed its internal buffers to disk (and the closing of the file descriptor). Listening for the finish event for a fs Writable stream lets you know that the file descriptor has been closed and no more writes are going to occur.

like image 108
mscdex Avatar answered Sep 24 '22 11:09

mscdex