一尘不染

fs.createWriteStream是否不立即创建文件?

node.js

从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);
        })
    });
}

但是,由于我download()异步调用了数十次,因此很少有人报告错误,因为fs.renameSync抱怨无法在找到文件tempFile.path

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

我使用了相同的URL列表进行测试,但失败了大约30%。一次下载一个相同的URL列表。

测试了一下,我发现下面的代码

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

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

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


阅读 884

收藏
2020-07-07

共1个答案

一尘不染

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);
            });
        });
    });
}

为了您的测试:

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'));
});
2020-07-07