Reassembling file chunks produced in a multi-part

2019-04-02 02:25发布

问题:

I'm using the excellent flow.js library to handle file uploads. It's a resumable HTML5 upload that produces a bunch of chunks on the server that must be reassembled. For example, foo.mov might become

timestamp-foomov.1
timestamp-foomov.2
...
timestamp-foomov.n

Uploads are working but I'm having trouble recombining the parts into a single binary. I have the following code from the Node.js server example the library authors provided on Github (https://github.com/flowjs/flow.js/tree/master/samples/Node.js).

  $.write = function(identifier, writableStream, options) {
  options = options || {};
  options.end = (typeof options['end'] == 'undefined' ? true : options['end']);

  // Iterate over each chunk
  var pipeChunk = function(number) {

      var chunkFilename = getChunkFilename(number, identifier);
      fs.exists(chunkFilename, function(exists) {

          if (exists) {
              // If the chunk with the current number exists,
              // then create a ReadStream from the file
              // and pipe it to the specified writableStream.
              var sourceStream = fs.createReadStream(chunkFilename);
              sourceStream.pipe(writableStream, {
                  end: false
              });
              sourceStream.on('end', function() {
                  // When the chunk is fully streamed,
                  // jump to the next one
                  pipeChunk(number + 1);
              });
          } else {
              // When all the chunks have been piped, end the stream
              if (options.end) writableStream.end();
              if (options.onDone) options.onDone();
          }
      });
  }
  pipeChunk(1);
  }

I'm invoking this code with the following route and am expecting it to produce a reassembled binary in the tmp directory (that's where I'm saving my chunks). However nothing is happening. What am I missing?

exports.download = function(req, res, next) {
switch(req.method) {
    case 'GET':
    var stream = fs.createWriteStream('foobar');
    flow.write(req.params.identifier, res);
    break;
}
}

回答1:

Reassembling all chunks is easy, just call this:

     var stream = fs.createWriteStream(filename);
     r.write(identifier, stream);

And that is it!

But other question is, when this method should be called? Maybe when all chunks are uploaded and present at tmp folder.

But there is another issue with duplicate calls of the done. This can be solved by creating and locking the file, once all chunks exists. Then call

    r.write(identifier, stream);

Then clean all chunks, release the lock and close the file.

Same approuch is done in php server side library: https://github.com/flowjs/flow-php-server/blob/master/src/Flow/File.php#L102