fs.createWriteStream不会立即创build文件?

我已经做了一个简单的下载http函数(error handling省略简化):

function download(url, tempFilepath, filepath, callback) { var tempFile = fs.createWriteStream(tempFilepath); http.request(url, function(res) { res.on('data', function(chunk) { tempFile.write(chunk); }).on('end', function() { tempFile.end(); fs.renameSync(tempFile.path, filepath); return callback(filepath); }) }); } 

然而,由于我几次asynchronous调用download()几十次,所以很less报告fs.renameSync错误,抱怨它在tempFile.path找不到文件。

 Error: ENOENT, no such file or directory 'xxx' 

我使用了相同的URL列表来testing它,并且大概30%的时间都失败了。 当下载一个一个的时候,同样的url列表也能正常工作。

testing一些,我发现了下面的代码

 fs.createWriteStream('anypath'); console.log(fs.exist('anypath')); console.log(fs.exist('anypath')); console.log(fs.exist('anypath')); 

并不总是打印true ,但有时第一个答案打印false

我怀疑太多的asynchronousfs.createWriteStream调用不能保证文件的创build。 这是真的? 有什么方法可以保证文件的创build吗?

您不应该在您的tempFile写入stream中调用write ,直到您从stream中收到'open'事件。 该文件将不会存在,直到您看到该事件。

对于你的function:

 function download(url, tempFilepath, filepath, callback) { var tempFile = fs.createWriteStream(tempFilepath); tempFile.on('open', function(fd) { http.request(url, function(res) { res.on('data', function(chunk) { tempFile.write(chunk); }).on('end', function() { tempFile.end(); fs.renameSync(tempFile.path, filepath); return callback(filepath); }); }); }); } 

为了您的testing:

 var ws = fs.createWriteStream('anypath'); ws.on('open', function(fd) { console.log(fs.existsSync('anypath')); console.log(fs.existsSync('anypath')); console.log(fs.existsSync('anypath')); }); 

接受的答案没有下载我的最后一些字节。
这是一个正常工作的Q版本(但没有临时文件)。

 'use strict'; var fs = require('fs'), http = require('http'), path = require('path'), Q = require('q'); function download(url, filepath) { var fileStream = fs.createWriteStream(filepath), deferred = Q.defer(); fileStream.on('open', function () { http.get(url, function (res) { res.on('error', function (err) { deferred.reject(err); }); res.pipe(fileStream); }); }).on('error', function (err) { deferred.reject(err); }).on('finish', function () { deferred.resolve(filepath); }); return deferred.promise; } module.exports = { 'download': download }; 

注意我正在监听文件stream而不是end响应。