我在尝试通过HTTP下载文件时使用以下代码。我试图使用流,因为文件非常大。我遇到的问题是,在将响应传递给创建的WritableStream之后,有时文件没有被创建,因此在检查校验和时代码会出错。
换句话说,'完成'即使文件不存在/尚未创建,WritableStream的事件也会触发。
exports.downloadHttpFile = function(url, path, mimeType, checksum) {
return exports.get(url, mimeType, false).then(function(res) {
if (res.statusCode != 200) {
return Promise.reject(new Error('Invalid response from server when trying to download file'))
} else {
return new Promise(function(resolve, reject) {
console.log('creating file at ' + path)
const writable = fs.createWriteStream(path);
writable.once('open', () => res.pipe(writable).once('error', reject)).on('finish', function() {
writable.end();
try {
if (checksum) {
console.log(checksum)
if (!checksum.hashType || !checksum.hashEncoding || !checksum.hashValue) return reject(new Error('Invalid checksum object'))
fs.createReadStream(path)
.once('error', function() {
console.log('ERRORS OUT HERE, FILE NO EXIST (path not created by fs.createWriteStream)')
})
.pipe(require('crypto').createHash(checksum.hashType).setEncoding(checksum.hashEncoding))
.once('finish', function() {
const fileHash = this.read();
if (fileHash != checksum.hashValue) {
try {
fs.unlinkSync(path);
} catch (err) {}
return reject(new Error('Downladed file checksum did not match given checksum'));
} else {
return resolve(path);
}
}).once('error', reject)
} else {
return resolve(path);
}
} catch (err) {
console.log('File did not exist after piping to writable stream..')
return reject(err);
}
}).once('error', reject);
});
}
})
}
有人可以这么好,告诉我哪里出错了吗?感谢
答案 0 :(得分:0)
我设法通过检查文件是否存在以及是否不调用downloadHttpFile来解决此问题。我知道这不是一个非常好的解决方案,我不确定为什么它会在文件尚未创建的情况下触发完成事件..但是除非有人有更好的解决方案,否则它现在会做。
代码如下:
exports.downloadHttpFile = function (url, path, mimeType, checksum) {
return exports.get(url, mimeType, false).then(function (res) {
if (res.statusCode != 200) {
return Promise.reject(new Error('Invalid response from server when trying to download file'))
} else {
return new Promise(function (resolve, reject) {
const writable = fs.createWriteStream(path)
writable.on('finish', function () {
let pathExists = false
try {
fs.statSync(path)
pathExists = true
} catch (err) {}
if (pathExists) {
if (checksum) {
console.log(checksum)
if (!checksum.hashType || !checksum.hashEncoding || !checksum.hashValue) return reject(new Error('Invalid checksum object'))
console.log('creating read stream for path ' + path)
fs.createReadStream(path)
.pipe(require('crypto').createHash(checksum.hashType).setEncoding(checksum.hashEncoding).once('error', function (err) {
console.log('Error creating crc code')
return reject(err)
}))
.once('finish', function () {
console.log('Finished reading stream')
const fileHash = this.read()
if (fileHash != checksum.hashValue) {
console.log('Checksums did not match')
console.log(fileHash)
console.log(checksum.hashValue)
return reject(new Error('Downladed file checksum did not match given checksum'))
} else {
console.log('Checksums matched')
return resolve(path)
}
}).once('error', reject)
} else {
return resolve(path)
}
} else {
console.log('File did not exist.. attempting to redownload' + path)
return resolve(exports.downloadHttpFile(url, path, mimeType, checksum))
}
}).on('error', function (err) {
console.log(err)
return reject(err)
})
res.pipe(writable).on('error', function (err) {
console.log('Error reading response')
return reject(err)
})
})
}
})
}