我从http函数下载了一个简单的下载(为简化省略了错误处理):
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);
})
});
}
Run Code Online (Sandbox Code Playgroud)
但是,由于我download()异步调用了几十次,它很少报告fs.renameSync抱怨它无法找到文件的错误tempFile.path.
Error: ENOENT, no such file or directory 'xxx'
Run Code Online (Sandbox Code Playgroud)
我使用相同的网址列表来测试它,它失败了大约30%的时间.逐个下载时,网址列表相同.
测试了一些,我发现了以下代码
fs.createWriteStream('anypath');
console.log(fs.exist('anypath'));
console.log(fs.exist('anypath'));
console.log(fs.exist('anypath'));
Run Code Online (Sandbox Code Playgroud)
并不总是打印true,但有时打印第一个答案false.
我怀疑太多异步fs.createWriteStream调用无法保证文件创建.这是真的?有没有什么方法可以保证文件的创建?
Joh*_*yHK 63
write在您从流中tempFile收到'open'事件之前,不应该调用您的写入流.在您看到该事件之前,该文件将不存在.
为了你的功能:
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);
});
});
});
}
Run Code Online (Sandbox Code Playgroud)
为了您的测试:
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'));
});
Run Code Online (Sandbox Code Playgroud)
Dan*_*mov 14
接受的答案没有为我下载一些最后的字节.
这是一个正常工作的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
};
Run Code Online (Sandbox Code Playgroud)
注意我正在收听finish文件流而不是end响应.