在尝试学习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);
});
});
问题在于,由于异步调用,数据块不一定按照接收顺序附加。典型的控制台输出如下所示:
我的问题是,以非阻塞方式实现此功能的正确方法是什么,但强制执行顺序。我看过像async这样的库,但是真的希望能够处理每个库,而不是创建一个系列并在所有文件块都进入后运行。我仍然试着把我的思想包裹起来这个事件驱动流程,所以任何指针都很棒。
答案 0 :(得分:3)
通常你会使用一个队列来等待写入的数据,然后每当前一个追加完成时,你会尝试写下一个。像这样:
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);
});
您需要展开此内容,以根据fileName保留parts
和inProgress
的队列。我的例子假设为了简单起见,这些将是不变的。
答案 1 :(得分: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'