有没有机会使用带有进度信息和快速的Node.js复制大文件?
解决方案1:fs.createReadStream().pipe(...)=无用,比原生cp慢5
请参阅:在node.js中复制文件的最快方法,可以使用进度信息(使用npm包'progress-stream'):
fs = require('fs');
fs.createReadStream('test.log').pipe(fs.createWriteStream('newLog.log'));
Run Code Online (Sandbox Code Playgroud)
这种方式的唯一问题是它比"cp source dest"容易长5倍.有关完整的测试代码,另请参阅下面的附录.
解决方案2:rsync --- info = progress2 =同样缓慢,因为解决方案1 =无用
解决方案3:我最后的办法,为node.js编写一个本机模块,使用"CoreUtils"(用于cp和其他的linux源代码)或其他函数,如快速文件复制中所示
有谁知道比解决方案3更好?我想避免使用本机代码,但它似乎最合适.
谢谢!我们欢迎任何套餐推荐或提示(尝试所有fs**)!
附录:
测试代码,使用管道和进度:
var path = require('path');
var progress = require('progress-stream');
var fs = require('fs');
var _source = path.resolve('../inc/big.avi');// 1.5GB
var _target= '/tmp/a.avi';
var stat = fs.statSync(_source);
var str = progress({
length: stat.size,
time: 100
});
str.on('progress', function(progress) {
console.log(progress.percentage);
});
function copyFile(source, target, cb) {
var cbCalled = false;
var rd = fs.createReadStream(source);
rd.on("error", function(err) {
done(err);
});
var wr = fs.createWriteStream(target);
wr.on("error", function(err) {
done(err);
});
wr.on("close", function(ex) {
done();
});
rd.pipe(str).pipe(wr);
function done(err) {
if (!cbCalled) {
console.log('done');
cb && cb(err);
cbCalled = true;
}
}
}
copyFile(_source,_target);
Run Code Online (Sandbox Code Playgroud)
更新:快速(详细进展!)C版本在这里实现:https://github.com/MidnightCommander/mc/blob/master/src/filemanager/file.c#L1480.似乎是最好的去处:-)
可能会减慢进程的一个方面与 console.log 相关。看看这段代码:
const fs = require('fs');
const sourceFile = 'large.exe'
const destFile = 'large_copy.exe'
console.time('copying')
fs.stat(sourceFile, function(err, stat){
const filesize = stat.size
let bytesCopied = 0
const readStream = fs.createReadStream(sourceFile)
readStream.on('data', function(buffer){
bytesCopied+= buffer.length
let porcentage = ((bytesCopied/filesize)*100).toFixed(2)
console.log(porcentage+'%') // run once with this and later with this line commented
})
readStream.on('end', function(){
console.timeEnd('copying')
})
readStream.pipe(fs.createWriteStream(destFile));
})
Run Code Online (Sandbox Code Playgroud)
以下是复制 400mb 文件的执行时间:
使用 console.log:692.950 毫秒
没有 console.log:382.540ms