2

在尝试学习 node.js/socket.io 时,我一直在搞乱创建一个简单的文件上传器,它从客户端浏览器获取数据块并在服务器端重新组装。

用于接收块的 socket.io 事件如下所示:

socket.on('sendChunk', function (data) {
    fs.appendFile(path + fileName, data.data, function (err) {
      if (err) 
       throw err;
      console.log(data.sequence + ' - The data was appended to file ' + fileName);
    });
  });

问题是由于异步调用,数据块不一定按照接收顺序附加。典型的控制台输出如下所示:

  • 1 - 数据附加到文件 testfile.txt
  • 3 - 数据附加到文件 testfile.txt
  • 4 - 数据附加到文件 testfile.txt
  • 2 - 数据附加到文件 testfile.txt

我的问题是,以非阻塞方式实现此功能但强制执行顺序的正确方法是什么。我看过像async这样的库,但我真的希望能够处理每一个库,而不是创建一个系列并在所有文件块都进入后运行。我仍然试图围绕所有这些事件驱动流,所以任何指针都很棒。

4

2 回答 2

4

通常,您会为等待写入的数据使用队列,然后每当前一个追加完成时,您就会尝试写入下一段。像这样的东西:

var parts = [];
var inProgress = false;
function appendPart(data){
  parts.push(data);
  writeNextPart();
}

function writeNextPart(){
  if (inProgress || parts.length === 0) return;

  var data = parts.shift();
  inProgress = true;
  fs.appendFile(path + fileName, data.data, function (err) {
    inProgress = false;
    if (err) throw err;
    console.log(data.sequence + ' - The data was appended to file ' + fileName);

    writeNextPart();
  });
}

socket.on('sendChunk', function (data) {
  appendPart(data);
});

您将需要扩展它以保留基于文件名的parts队列inProgress。为了简单起见,我的示例假设这些将是恒定的。

于 2013-02-17T03:28:39.697 回答
0

因为您需要附加顺序或同步。您可以使用fs.appendFileSync而不是fs.appendFile. 这是处理它的最快方法,但它会损害性能。

如果您想自己异步处理它,请使用使用EventEmitter. 事实证明,响应(以及请求)对象都是流。创建一个可写流fs.createWriteStream并写入所有片段以附加文件。

fs.createWriteStream(path, [options])#
Returns a new WriteStream object (See Writable Stream).

options is an object with the following defaults:

{ flags: 'w',
  encoding: null,
  mode: 0666 }

在您的情况下,您将使用标志:'a'

于 2013-02-17T15:59:44.750 回答